serialization in the “builder monoid” and “builder monad” style.
In this style, we build up serialized data structures by
Writer monad with
do-notation. This style of serialization
has been used for a long time and we insist that it works really well.
This package provides a
Builder monoid and a
PutM monad which are roughly
equivalent to types of the same name in the Haskell
ArrayBuffer building must occur in
Create a two-byte
arraybuffer :: ArrayBuffer which contains the number -10 encoded as big-endian 16-bit two’s-complement.
import Data.ArrayBuffer.Builder (execPut, putInt16be) do arraybuffer :: ArrayBuffer <- execPut $ putInt16be (-10)
Create a 24-byte
arraybuffer :: ArrayBuffer which contains three big-endian
IEEE-754 double-precision floats.
import Data.ArrayBuffer.Builder (execPut, putFloat64be) do arraybuffer :: ArrayBuffer <- execPut do putFloat64be 1.0 putFloat64be 2.0 putFloat64be 3.0
String as UTF8 with a length prefix into our
We give this as an example, rather than supporting it in the library, because
it depends on
import Data.ArrayBuffer.Builder (PutM, putArrayBuffer, execPut) import Data.ArrayBuffer.Typed (buffer) import Data.ArrayBuffer.ArrayBuffer (byteLength) import Web.Encoding.TextEncoder (new, textEncoder) putStringUtf8 :: forall m. MonadEffect m => String -> PutM m Unit putStringUtf8 s = do textEncoder <- liftEffect new let stringbuf = buffer $ encode s textEncoder -- Put a 32-bit big-endian length for the utf8 string, in bytes. putInt32be $ byteLength stringbuf putArrayBuffer stringbuf arraybuffer :: ArrayBuffer <- execPut $ putStringUtf8 "🦝"
import Data.ArrayBuffer.Builder (execPut, putInt32be) import Data.Foldable (traverse_) import Data.Array (length) putArrayInt32 :: forall m. MonadEffect m => Array Int -> PutM m Unit putArrayInt32 xs = do -- Put a 64-bit big-endian length prefix for the array. putInt32be 0 putInt32be $ length xs traverse_ putInt32be xs do arraybuffer <- execPut $ putArrayInt32 [1,2,3]
Stack-safe version of the
putArrayInt32 function above. For stack-safety
foldRecM instead of
foldRecM has a
constraint which makes it stack-safe.
import Data.Array (foldRecM) putArrayInt32 :: forall m. MonadEffect m => MonadRec m => Array Int -> PutM m Unit putArrayInt32 xs = do -- Put a 64-bit big-endian length prefix for the array. putInt32be 0 putInt32be $ length xs foldRecM (\_ x -> putInt32be x) unit xs
This package will always be stack-safe if all of the functions called inside
PutM builder expression are stack-safe.
This package is only for writing
ArrayBuffers, not reading them.
for a way to deserialize from
ArrayBuffer back to Purescript data.
To run the tests,
spago -x spago-dev.dhall test