Skip to content

justinwoo/purescript-arraybuffer-builder

 
 

Repository files navigation

purescript-arraybuffer-builder

CI Pursuit

ArrayBuffer serialization in the “builder monoid” and “builder monad” style. In this style, we build up serialized data structures by appending to a monoid in a 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 Data.Binary.Put module.

This package defines no typeclasses. Typeclass-based serialization/deserialization generally assumes that we are round-tripping some data structures out to storage and then back into our program. This package is designed for the case in which we are serializing some data to be sent to another program which expects a serialization format that we don't control.

Usage Examples

All ArrayBuffer building must occur in Effect.

Serialize an integer

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)

Serialize three floats

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

Serialize a String as UTF8

Encode a String as UTF8 with a length prefix into our Builder.

We give this as an example, rather than supporting it in the library, because it depends on Data.TextEncoding.encodeUtf8.

import Data.ArrayBuffer.Builder (PutM, putArrayBuffer, execPut)
import Data.ArrayBuffer.Typed (buffer)
import Data.TextEncoding (encodeUtf8)
import Data.ArrayBuffer.ArrayBuffer (byteLength)

putStringUtf8 :: forall m. (MonadEffect m) => String -> PutM m Unit
putStringUtf8 s = do
  let stringbuf = buffer $ encodeUtf8 s
  -- Put a 32-bit big-endian length prefix for the length of the utf8 string, in bytes.
  putInt32be $ byteLength stringbuf
  putArrayBuffer stringbuf

do
  arraybuffer :: ArrayBuffer <- execPut $ putStringUtf8 "BLM"

Serialize an Array Int

Encode an Array Int with a length prefix in a way that's compatible with the Binary instance for [Int32] from the Haskell binary library.

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 length of the array.
    putInt32be 0
    putInt32be $ length xs
    traverse_ putInt32be xs

do
  arraybuffer <- execPut $ putArrayInt32 [1,2,3]

unsafePerformEffect execPut

Dear computer programmer, you can call execPut inside unsafePerformEffect.

The reason why this whole library is Effectful is that ArrayBuffers are mutable, so the ArrayBuffer library functions do everything in Effect to to confirm that any mutations are properly sequenced.

However, all of the put functions in this library are actually side-effect free, so we can use unsafePerformEffect to tell the compiler to trust us that we don't perform any side-effects while we're building an ArrayBuffer.

let serialized :: ArrayBuffer
    serialized = unsafePerformEffect $ execPut do
        putInt32be 3                                -- ✅ Good, this has no side-effects
        putInt32be =<< getCurrentPosixTime          -- ❌ No don't do this
        putArrayBuffer =<< readFileFromMyFilesystem -- ❌ No don’t do this either

Deserialization

This package is only for writing ArrayBuffers, not reading them. See purescript-parsing-dataview for a way to deserialize from ArrayBuffer back to Purescript data.

References

Alternative packages for serializing to an ArrayBuffer

About

ArrayBuffer builder for Purescript

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages

  • PureScript 81.3%
  • Dhall 15.4%
  • Nix 3.3%