{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
module Capnp.Convert
( msgToBuilder
, msgToLBS
, msgToBS
, msgToValue
, bsToMsg
, bsToValue
, lbsToMsg
, lbsToValue
, valueToBuilder
, valueToBS
, valueToLBS
, valueToMsg
) where
import Control.Monad ((>=>))
import Control.Monad.Catch (MonadThrow)
import Data.Foldable (foldlM)
import Data.Functor.Identity (runIdentity)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Lazy as LBS
import Capnp.Classes
import Capnp.Bits (WordCount)
import Capnp.TraversalLimit (LimitT, MonadLimit, evalLimitT)
import Codec.Capnp (getRoot, setRoot)
import Data.Mutable (freeze)
import qualified Capnp.Message as M
limitFromMsg :: (MonadThrow m, M.Message m msg) => msg -> m WordCount
limitFromMsg msg = do
messageWords <- countMessageWords
pure (messageWords * 10)
where
countMessageWords = do
segCount <- M.numSegs msg
foldlM
(\total i -> do
words <- M.getSegment msg i >>= M.numWords
pure (words + total)
)
0
[0..segCount - 1]
msgToBuilder :: M.ConstMsg -> BB.Builder
msgToBuilder = runIdentity . M.encode
msgToLBS :: M.ConstMsg -> LBS.ByteString
msgToLBS = BB.toLazyByteString . msgToBuilder
msgToBS :: M.ConstMsg -> BS.ByteString
msgToBS = LBS.toStrict . msgToLBS
msgToValue :: (MonadThrow m, M.Message (LimitT m) msg, M.Message m msg, FromStruct msg a) => msg -> m a
msgToValue msg = do
limit <- limitFromMsg msg
evalLimitT limit (getRoot msg)
bsToMsg :: MonadThrow m => BS.ByteString -> m M.ConstMsg
bsToMsg = M.decode
bsToValue :: (MonadThrow m, FromStruct M.ConstMsg a) => BS.ByteString -> m a
bsToValue = bsToMsg >=> msgToValue
lbsToMsg :: MonadThrow m => LBS.ByteString -> m M.ConstMsg
lbsToMsg = bsToMsg . LBS.toStrict
lbsToValue :: (MonadThrow m, FromStruct M.ConstMsg a) => LBS.ByteString -> m a
lbsToValue = bsToValue . LBS.toStrict
valueToBuilder :: (MonadLimit m, M.WriteCtx m s, Cerialize a, ToStruct (M.MutMsg s) (Cerial (M.MutMsg s) a)) => a -> m BB.Builder
valueToBuilder val = msgToBuilder <$> (valueToMsg val >>= freeze)
valueToBS :: (MonadLimit m, M.WriteCtx m s, Cerialize a, ToStruct (M.MutMsg s) (Cerial (M.MutMsg s) a)) => a -> m BS.ByteString
valueToBS = fmap LBS.toStrict . valueToLBS
valueToLBS :: (MonadLimit m, M.WriteCtx m s, Cerialize a, ToStruct (M.MutMsg s) (Cerial (M.MutMsg s) a)) => a -> m LBS.ByteString
valueToLBS = fmap BB.toLazyByteString . valueToBuilder
valueToMsg :: (MonadLimit m, M.WriteCtx m s, Cerialize a, ToStruct (M.MutMsg s) (Cerial (M.MutMsg s) a)) => a -> m (M.MutMsg s)
valueToMsg val = do
msg <- M.newMessage Nothing
ret <- cerialize msg val
setRoot ret
pure msg