git.iko.soy/rowtype-yoga/purescript-arraybuffer-builder
on a2a090c help sign in
140 lines 4.9 kB history raw
1# purescript-arraybuffer-builder
3[![CI](https://github.com/jamesdbrock/purescript-arraybuffer-builder/workflows/CI/badge.svg?branch=master)](https://github.com/jamesdbrock/purescript-arraybuffer-builder/actions)
4[![Pursuit](http://pursuit.purescript.org/packages/purescript-arraybuffer-builder/badge)](http://pursuit.purescript.org/packages/purescript-arraybuffer-builder/)
7[`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
8serialization in the “builder monoid” and “builder monad” style.
9In this style, we build up serialized data structures by `tell`ing to
10a `Writer` monad with `do`-notation. This style of serialization
11has been used for a long time and we [insist that it works really well](https://wiki.haskell.org/Do_notation_considered_harmful#Library_design).
13This package provides a `Builder` monoid and a `PutM` monad which are roughly
14equivalent to types of the same name in the Haskell
15[__Data.Binary.Put__](https://hackage.haskell.org/package/binary/docs/Data-Binary-Put.html)
16module.
18## Usage Examples
20All `ArrayBuffer` building must occur in `Effect`.
22### Serialize an integer
24Create a two-byte `arraybuffer :: ArrayBuffer` which contains the number *-10* encoded as big-endian 16-bit two’s-complement.
25```purescript
26import Data.ArrayBuffer.Builder (execPut, putInt16be)
28do
29 arraybuffer :: ArrayBuffer <- execPut $ putInt16be (-10)
30```
32### Serialize three floats
34Create a 24-byte `arraybuffer :: ArrayBuffer` which contains three big-endian
35IEEE-754 double-precision floats.
37```purescript
38import Data.ArrayBuffer.Builder (execPut, putFloat64be)
40do
41 arraybuffer :: ArrayBuffer <- execPut do
42 putFloat64be 1.0
43 putFloat64be 2.0
44 putFloat64be 3.0
45```
47### Serialize a `String` as UTF8
49Encode a `String` as UTF8 with a length prefix into our `Builder`.
51We give this as an example, rather than supporting it in the library, because
52it depends on
53[`Data.TextEncoding.encodeUtf8`](https://pursuit.purescript.org/packages/purescript-text-encoding/docs/Data.TextEncoding#v:encodeUtf8).
55```purescript
56import Data.ArrayBuffer.Builder (PutM, putArrayBuffer, execPut)
57import Data.ArrayBuffer.Typed (buffer)
58import Data.TextEncoding (encodeUtf8)
59import Data.ArrayBuffer.ArrayBuffer (byteLength)
61putStringUtf8 :: forall m. MonadEffect m => String -> PutM m Unit
62putStringUtf8 s = do
63 let stringbuf = buffer $ encodeUtf8 s
64 -- Put a 32-bit big-endian length prefix for the length of the utf8 string, in bytes.
65 putInt32be $ byteLength stringbuf
66 putArrayBuffer stringbuf
68do
69 arraybuffer :: ArrayBuffer <- execPut $ putStringUtf8 "BLM"
70```
72### Serialize an `Array Int`
74Encode an `Array Int` with a length prefix in a
75way that's compatible with the
76[`Binary` instance for `[Int32]`](https://hackage.haskell.org/package/binary/docs/Data-Binary.html#t:Binary)
77from the Haskell
78[__binary__](https://hackage.haskell.org/package/binary)
79library.
81```purescript
82import Data.ArrayBuffer.Builder (execPut, putInt32be)
83import Data.Foldable (traverse_)
84import Data.Array (length)
86putArrayInt32 :: forall m. MonadEffect m => Array Int -> PutM m Unit
87putArrayInt32 xs = do
88 -- Put a 64-bit big-endian length prefix for the length of the array.
89 putInt32be 0
90 putInt32be $ length xs
91 traverse_ putInt32be xs
93do
94 arraybuffer <- execPut $ putArrayInt32 [1,2,3]
95```
97### Serialize an `Array Int` stack-safe
99Stack-safe version of the `putArrayInt32` function above. For stack-safety
100we use `foldRecM` instead of `traverse_` because `foldRecM` has a `MonadRec`
101constraint which makes it stack-safe.
103```purescript
104import Data.Array (foldRecM)
106putArrayInt32 :: forall m. MonadEffect m => MonadRec m => Array Int -> PutM m Unit
107putArrayInt32 xs = do
108 -- Put a 64-bit big-endian length prefix for the length of the array.
109 putInt32be 0
110 putInt32be $ length xs
111 foldRecM (\_ x -> putInt32be x) unit xs
112```
114## Stack-safety
116This package will always be stack-safe if all of the functions called inside
117of the `PutM` builder expression are stack-safe.
119## Deserialization
121This package is only for writing `ArrayBuffer`s, not reading them.
122See
123[__purescript-parsing-dataview__](https://pursuit.purescript.org/packages/purescript-parsing-dataview/)
124for a way to deserialize from `ArrayBuffer` back to Purescript data.
126## Alternative packages for serializing to an `ArrayBuffer`
128* [__dynamic-buffers__](https://pursuit.purescript.org/packages/purescript-dynamic-buffers)
129* [__node-buffer__](https://pursuit.purescript.org/packages/purescript-node-buffer)
130* [__arraybuffer-class__](https://pursuit.purescript.org/packages/purescript-arraybuffer-class)
131* [__bytestrings__](https://pursuit.purescript.org/packages/purescript-bytestrings/)
132* [__array-builder__](https://pursuit.purescript.org/packages/purescript-array-builder)
134## Development
136To run the tests,
138```shell
139spago -x spago-dev.dhall test
140```