@@ -57,19 +57,20 @@
5757-- | __bytestring-tree-builder__
5858-- | which “according to the benchmarks … beats all the alternatives.”
5959-- | However, we
60−-- | haven't chosen this implementation because it's fast, we've chosen
61−-- | this implementation because it's simple.
62−-- | If someone wants to create a fast PureScript ArrayBuffer serialization
60+-- | haven’t chosen this implementation because it’s fast, we've chosen
61+-- | this implementation because it’s simple.
62+-- | If someone wants to create a fast PureScript `ArrayBuffer` serialization
6363-- | library, then they can benchmark against this one to prove that the new
6464-- | one is fast.
6565-- |
6666-- | One relatively cheap and simple performance improvement for this library would be to
67−-- | remove the Null constructor of `Builder` and instead use Javascript nulls.
68−-- | __UPDATE__ Actually no, we need the Null constructor for the Monoid instance.
67+-- | remove the `Null` constructor of `Builder` and instead use Javascript nulls?
6968-- |
7069-- | In the longer term, it might make sense to try to change the `Builder` so
7170-- | that it works like the
72−-- | https://hackage.haskell.org/package/bytestring/docs/Data-ByteString-Builder.html
71+-- | https://hackage.haskell.org/package/bytestring/docs/Data-ByteString-Builder.html .
72+-- | That’s the approach taken by
73+-- | https://pursuit.purescript.org/packages/purescript-dynamic-buffers .
7374-- |
7475-- | Here are some benchmarks of different Haskell ByteString builders
7576-- | https://github.com/haskell-perf/strict-bytestring-builders
@@ -77,27 +78,18 @@
7778-- | We've tried to design the API for this library with minimal assumptions,
7879-- | so that if we want to change the `Builder` implementation later then we can.
7980-- |
80−-- | Another way this could go:
81−-- | https://kodimensional.dev/posts/2019-03-25-comonadic-builders
82−-- |
83−-- | Our convention is that functions which add `DataView`s to
84−-- | the `Builder` are suffixed with underscore (`_`).
85−-- |
8681module Data.ArrayBuffer.Builder.Internal
8782( Builder(..)
8883, (<>>)
89−, Bytes(..)
84+, DataBuff(..)
9085, toView
9186, execBuilder
9287, length
9388, foldl
9489, foldM
9590, singleton
96−, singleton_
9791, cons
98−, cons_
9992, snoc
100−, snoc_
10193, encodeUint8
10294, encodeInt8
10395, encodeUint16be
@@ -127,6 +119,19 @@ import Data.UInt (UInt)
127119import Effect (Effect)
128120import Effect.Class (class MonadEffect, liftEffect)
129121
122+-- | For distinguishing between `ArrayBuffer` and `DataView`.
123+data DataBuff
124+ = Buff ArrayBuffer
125+ | View DataView
126+
127+-- Concerning DataViews.
128+-- https://v8.dev/blog/dataview
129+
130+ -- | View the contents of `DataBuff` as a `DataView`.
131+toView :: DataBuff -> DataView
132+toView (Buff ab) = DV.whole ab
133+toView (View dv) = dv
134+
130135-- | Monoidal builder for `ArrayBuffer`s.
131136-- |
132137-- | We can add two types of things to the `Builder`:
@@ -138,7 +143,7 @@ import Effect.Class (class MonadEffect, liftEffect)
138143-- | from some other `ArrayBuffer`, so that we don’t
139144-- | need an extra intermediate copy of the slice.
140145data Builder
141− = Node Builder Bytes Builder
146+ = Node Builder DataBuff Builder
142147 | Null
143148
144149-- | ### Left-associative `<>>` append operator
@@ -193,57 +198,35 @@ infixl 5 append as <>>
193198instance monoidBuilder :: Monoid Builder where
194199 mempty = Null
195200
196−-- | For distinguishing between `ArrayBuffer` and `DataView`.
197−data Bytes
198− = ByteBuff ArrayBuffer
199− | ByteView DataView
200−
201201-- | `Builder` is not an instance of `Foldable` because `Builder` is monomorphic.
202−foldl :: forall b. (b -> Bytes -> b) -> b -> Builder -> b
202+foldl :: forall b. (b -> DataBuff -> b) -> b -> Builder -> b
203203foldl _ a Null = a
204204foldl f a (Node l x r) = foldl f (f (foldl f a l) x) r
205205
206206-- | Monomorphic foldM copied from
207207-- | [`Data.Foldable.foldM`](https://pursuit.purescript.org/packages/purescript-foldable-traversable/4.1.1/docs/Data.Foldable#v:foldM)
208−foldM :: forall b m. (Monad m) => (b -> Bytes -> m b) -> b -> Builder -> m b
208+foldM :: forall b m. (Monad m) => (b -> DataBuff -> m b) -> b -> Builder -> m b
209209foldM f a0 = foldl (\ma b -> ma >>= flip f b) (pure a0)
210210
211−-- | Construct a `Builder` with a single `ArrayBuffer`. *O(1)*
212−singleton :: ArrayBuffer -> Builder
213−singleton buf = Node Null (ByteBuff buf) Null
214−
215−-- | Construct a `Builder` with a single `DataView`. *O(1)*
216−singleton_ :: DataView -> Builder
217−singleton_ buf = Node Null (ByteView buf) Null
211+-- | Construct a `Builder` with a single `DataBuff`. *O(1)*
212+singleton :: DataBuff -> Builder
213+singleton buf = Node Null buf Null
218214
219215-- | Calculate the total byte length of the `Builder`, without actually
220216-- | building it yet. *O(n)*
221217length :: Builder -> ByteLength
222218length bldr = foldl (\b a -> b + len a) 0 bldr
223219 where
224− len (ByteBuff ab) = AB.byteLength ab
225− len (ByteView dv) = DV.byteLength dv
226−
227− -- | View the contents of `Bytes` as a `DataView`.
228−toView :: Bytes -> DataView
229−toView (ByteBuff ab) = DV.whole ab
230−toView (ByteView dv) = dv
231−
232−-- | Prepend an `ArrayBuffer` to the beginning of the `Builder`. *O(1)*
233−cons :: ArrayBuffer -> Builder -> Builder
234−cons x bs = Node Null (ByteBuff x) bs
235−
236−-- | Prepend a `DataView` to the beginning of the `Builder`. *O(1)*
237−cons_ :: DataView -> Builder -> Builder
238−cons_ x bs = Node Null (ByteView x) bs
220+ len (Buff ab) = AB.byteLength ab
221+ len (View dv) = DV.byteLength dv
239222
240−-- | Append an `ArrayBuffer` to the end of the `Builder`. *O(1)*
241−snoc :: Builder -> ArrayBuffer -> Builder
242−snoc bs x = Node bs (ByteBuff x) Null
223+-- | Prepend a `DataBuff` to the beginning of the `Builder`. *O(1)*
224+cons :: DataBuff -> Builder -> Builder
225+cons x bs = Node Null x bs
243226
244−-- | Append a `DataView` to the end of the `Builder`. *O(1)*
245−snoc_ :: Builder -> DataView -> Builder
246−snoc_ bs x = Node bs (ByteView x) Null
227+-- | Append a `DataBuff` to the end of the `Builder`. *O(1)*
228+snoc :: Builder -> DataBuff -> Builder
229+snoc bs x = Node bs x Null
247230
248231-- | Build a single `ArrayBuffer` from a `Builder`. *O(n)*
249232execBuilder :: forall m. (MonadEffect m) => Builder -> m ArrayBuffer
@@ -263,9 +246,9 @@ execBuilder bldr = do
263246 ) 0 bldr
264247 pure buf
265248 where
266− toUint8Array :: Bytes -> Effect Uint8Array
267− toUint8Array (ByteBuff ab) = AT.whole ab
268− toUint8Array (ByteView dv) =
249+ toUint8Array :: DataBuff -> Effect Uint8Array
250+ toUint8Array (Buff ab) = AT.whole ab
251+ toUint8Array (View dv) =
269252 AT.part (DV.buffer dv) (DV.byteOffset dv) (DV.byteLength dv)
270253
271254-- | Serialize an 8-bit unsigned integer (byte) into a new `ArrayBuffer`.