mirror of
https://github.com/zap-proto/haskell.git
synced 2026-10-30 15:05:00 +00:00
77 lines
2.7 KiB
Haskell
77 lines
2.7 KiB
Haskell
{- |
|
|
Module: Capnp.GenHelpers
|
|
Description: Misc. helpers for generated code.
|
|
|
|
This module provides various helpers used by generated code; developers
|
|
are not expected to invoke them directly.
|
|
|
|
These helpers are used by the low-level api. "Capnp.GenHelpers.Pure"
|
|
defines helpers used by high-level api.
|
|
-}
|
|
{-# LANGUAGE FlexibleContexts #-}
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
module Capnp.GenHelpers where
|
|
|
|
import Data.Bits
|
|
import Data.Word
|
|
|
|
import Data.Maybe (fromJust)
|
|
|
|
import qualified Data.ByteString as BS
|
|
|
|
import Capnp.Bits
|
|
|
|
import Capnp (bsToMsg, evalLimitT)
|
|
|
|
import qualified Capnp.Classes as C
|
|
import qualified Capnp.Message as M
|
|
import qualified Capnp.Untyped as U
|
|
|
|
-- | @'getWordField' struct index offset def@ fetches a field from the
|
|
-- struct's data section. @index@ is the index of the 64-bit word in the data
|
|
-- section in which the field resides. @offset@ is the offset in bits from the
|
|
-- start of that word to the field. @def@ is the default value for this field.
|
|
getWordField :: (U.ReadCtx m msg, C.IsWord a) => U.Struct msg -> Int -> Int -> Word64 -> m a
|
|
getWordField struct idx offset def = fmap
|
|
( C.fromWord
|
|
. xor def
|
|
. (`shiftR` offset)
|
|
)
|
|
(U.getData idx struct)
|
|
|
|
-- | @'setWordField' struct value index offset def@ sets a field in the
|
|
-- struct's data section. The meaning of the parameters are as in
|
|
-- 'getWordField', with @value@ being the value to set. The width of the
|
|
-- value is inferred from its type.
|
|
setWordField ::
|
|
( U.RWCtx m s
|
|
, Bounded a, Integral a, C.IsWord a, Bits a
|
|
)
|
|
=> U.Struct (M.MutMsg s) -> a -> Int -> Int -> Word64 -> m ()
|
|
setWordField struct value idx offset def = do
|
|
old <- U.getData idx struct
|
|
let new = replaceBits (value `xor` C.fromWord def) old offset
|
|
U.setData new idx struct
|
|
|
|
embedCapPtr :: M.WriteCtx m s => M.MutMsg s -> M.Client -> m (Maybe (U.Ptr (M.MutMsg s)))
|
|
embedCapPtr msg client =
|
|
Just . U.PtrCap <$> U.appendCap msg client
|
|
|
|
-- | Get a pointer from a ByteString, where the root object is a struct with
|
|
-- one pointer, which is the pointer we will retrieve. This is only safe for
|
|
-- trusted inputs; it reads the message with a traversal limit of 'maxBound'
|
|
-- (and so is suseptable to denial of service attacks), and it calls 'error'
|
|
-- if decoding is not successful.
|
|
--
|
|
-- The purpose of this is for defining constants of pointer type from a schema.
|
|
getPtrConst :: C.FromPtr M.ConstMsg a => BS.ByteString -> a
|
|
getPtrConst bytes = fromJust $ do
|
|
msg <- bsToMsg bytes
|
|
evalLimitT maxBound $ U.rootPtr msg >>= U.getPtr 0 >>= C.fromPtr msg
|
|
|
|
|
|
getTag :: U.ReadCtx m msg => U.Struct msg -> Int -> m Word16
|
|
getTag struct offset = do
|
|
word <- U.getData (offset `div` 4) struct
|
|
pure $ fromIntegral $ word `shiftR` ((offset `mod` 4) * 16)
|