git.iko.soy/rowtype-yoga/purescript-parsing-dataview
on master help sign in
Upgrade to parsing v9
commit6fa3f9a36a311327ae158e00fc30c1610c3cb247 authorJames Brock <jamesbrock@gmail.com> dateSat 7 May 2022, 15:56 (4 years ago) parent7745ac9
5 files changed+147−150
CHANGELOG.md+1−1 README.md+14−11 bower.json+10−10 src/Parsing/DataView.purs+97−110 test/Main.purs+25−18
CHANGELOG.md+1−1
@@ -4,7 +4,7 @@
44
55### Breaking changes
66
7−- Build for PureScript v0.15.0.
7+- Build for PureScript v0.15.0 with __parsing__ v9.0.0.
88
99## v2.1.0 2021-11-24
1010
README.md+14−11
@@ -3,16 +3,17 @@
33[![CI](https://github.com/jamesdbrock/purescript-parsing-dataview/workflows/CI/badge.svg?branch=master)](https://github.com/jamesdbrock/purescript-parsing-dataview/actions)
44[![Pursuit](http://pursuit.purescript.org/packages/purescript-parsing-dataview/badge)](http://pursuit.purescript.org/packages/purescript-parsing-dataview/)
55
6−Primitive parsers for parsing
7−`DataView`s on Javascript `ArrayBuffer`s with the package
6+Primitive parsers for
7+`DataView`s on JavaScript `ArrayBuffer`s with the package
88[__purescript-parsing__](https://pursuit.purescript.org/packages/purescript-parsing/).
99
1010With this package, the input stream support of __purescript-parsing__
11−roughly matches the built-in stream support of __Megaparsec__:
11+is similar to the built-in stream support of [__Megaparsec__](https://hackage.haskell.org/package/megaparsec):
1212
1313| Stream type | purescript-parsing | Megaparsec |
1414|----|-----|----|
15−| UTF-16 strings | String | Text |
15+| UTF-16 strings | String | Text < v2.0|
16+| UTF-8 strings | __DataView__ *see below* | Text ≥ v2.0 |
1617| Listy strings | Token | String |
1718| Binary blobs | __DataView__ | ByteString |
1819
@@ -24,14 +25,14 @@ Parse values out of a `dataview :: Data.ArrayBuffer.Types.DataView`. All
2425
2526### Parse two numbers
2627
27−Parse two big-endian IEEE 754 double-precision floats.
28+Parse two big-endian IEEE 754 double-precision `Number`s.
2829
2930```purescript
3031import Text.Parsing.Parser (runParserT)
3132import Text.Parsing.Parser.DataView (anyFloat64be)
3233
3334do
34− result <- runParserT dataview $ do
35+ result <- runParserT dataview do
3536 float1 <- anyFloat64be
3637 float2 <- anyFloat64be
3738 pure $ Tuple float1 float2
@@ -39,7 +40,7 @@ do
3940
4041### Parse an array
4142
42−Parse an array of `n` 32-bit signed integers.
43+Parse an array of `n` 32-bit big-endian signed `Int`s.
4344
4445```purescript
4546import Text.Parsing.Parser (runParserT)
@@ -52,7 +53,7 @@ do
5253
5354### Parse UTF8
5455
55−Parse a `String` as UTF8 with a length prefix.
56+Parse a UTF-8 `String` with a length prefix.
5657
5758We give this as an example, rather than supporting it in the library, because
5859it depends on
@@ -70,13 +71,15 @@ import Data.UInt (toInt)
7071import Data.Text.Decoding (decodeUtf8)
7172
7273
74+-- Make a `Uint8Array` Typed Array from a `DataView`. We can do this
75+-- for the case of `Uint8` because byte arrays are always aligned.
7376mkUint8Array :: DataView -> Effect Uint8Array
7477mkUint8Array dv = part (buffer dv) (byteOffset dv) (byteLength dv)
7578
7679do
77− result <- runParserT dataview $ do
78− -- Parse a 32-bit big-endian length prefix for the length of the utf8 string,
79− -- in bytes.
80+ result <- runParserT dataview do
81+ -- Parse a 32-bit big-endian length prefix for the length
82+ -- of the UTF-8 string in bytes.
8083 length <- anyUint32be
8184 stringview <- takeN $ toInt length
8285 stringarray <- lift $ liftEffect $ mkUint8Array stringview
bower.json+10−10
@@ -14,15 +14,15 @@
1414 "output"
1515 ],
1616 "dependencies": {
17− "purescript-arraybuffer": "^v11.0.1",
18− "purescript-arraybuffer-types": "^v3.0.0",
19− "purescript-effect": "^v3.0.0",
20− "purescript-float32": "^v1.0.0",
21− "purescript-maybe": "^v5.0.0",
22− "purescript-parsing": "^v6.0.2",
23− "purescript-prelude": "^v5.0.1",
24− "purescript-transformers": "^v5.1.0",
25− "purescript-tuples": "^v6.0.1",
26− "purescript-uint": "^v6.0.3"
17+ "purescript-arraybuffer": "^v13.0.0",
18+ "purescript-arraybuffer-types": "^v3.0.2",
19+ "purescript-effect": "^v4.0.0",
20+ "purescript-float32": "^v2.0.0",
21+ "purescript-maybe": "^v6.0.0",
22+ "purescript-parsing": "^v9.0.0",
23+ "purescript-prelude": "^v6.0.0",
24+ "purescript-transformers": "^v6.0.0",
25+ "purescript-tuples": "^v7.0.0",
26+ "purescript-uint": "^v7.0.0"
2727 }
2828}
src/Parsing/DataView.purs+97−110
@@ -1,24 +1,36 @@
1−-- | Primitive parsers for parsing Javascript ArrayBuffers with the
2−-- | [`Text.Parsing.Parser`](https://pursuit.purescript.org/packages/purescript-parsing/docs/Text.Parsing.Parser)
3−-- | module in package __purescript-parsing__.
1+-- | Primitive parsers for JavaScript `ArrayBuffer`s with the
2+-- | `ParserT` type and combinators in package __purescript-parsing__.
43-- | See the package README for usage examples.
54-- |
5+-- | ### Mutable ArrayBuffer
6+-- |
67-- | All of the parsers in this module operate on an input stream of
7−-- | [`Data.ArrayBuffer.Types.DataView`](https://pursuit.purescript.org/packages/purescript-arraybuffer-types/docs/Data.ArrayBuffer.Types#t:DataView),
8−-- | which represents a range of an
9−-- | `Data.ArrayBuffer.Types.ArrayBuffer`.
8+-- | [__Data.ArrayBuffer.Types.DataView__](https://pursuit.purescript.org/packages/purescript-arraybuffer-types/docs/Data.ArrayBuffer.Types#t:DataView),
9+-- | which represents a range of a mutable
10+-- | [__Data.ArrayBuffer.Types.ArrayBuffer__](https://pursuit.purescript.org/packages/purescript-arraybuffer-types/docs/Data.ArrayBuffer.Types#t:ArrayBuffer).
1011-- |
1112-- | For operations for working with `ArrayBuffer` and `DataView`, see
1213-- | module
13−-- | [`Data.ArrayBuffer.DataView`](https://pursuit.purescript.org/packages/purescript-arraybuffer/docs/Data.ArrayBuffer.DataView)
14+-- | [__Data.ArrayBuffer.DataView__](https://pursuit.purescript.org/packages/purescript-arraybuffer/docs/Data.ArrayBuffer.DataView)
1415-- | in package __purescript-arraybuffer__.
1516-- |
1617-- | Reading from an `ArrayBuffer` is an `Effect`ful activity, so
1718-- | all parsers in this module must be run in a
18−-- | `MonadEffect m => ParserT DataView m` context, with
19−-- | `Text.Parsing.Parser.runParserT`.
20−module Text.Parsing.Parser.DataView
21− ( anyPrim
19+-- | `MonadEffect m => ParserT DataView m` context with
20+-- | `Parsing.runParserT`.
21+-- |
22+-- | ### Position
23+-- |
24+-- | In a `DataView` parser, the `Position {index}` counts the number of
25+-- | bytes since the beginning of the input.
26+-- |
27+-- | The `Postion {line,column}` fields are unused and will remain constant *1*.
28+module Parsing.DataView
29+ ( takeN
30+ , takeRest
31+ , eof
32+ , match
33+ , anyPrim
2234 , anyInt8
2335 , anyInt16be
2436 , anyInt16le
@@ -48,96 +60,69 @@ module Text.Parsing.Parser.DataView
4860 , satisfyFloat32le
4961 , satisfyFloat64be
5062 , satisfyFloat64le
51− , takeN
52− , takeRest
53− , eof
54− , match
55− )
56− where
63+ ) where
5764
5865import Prelude
5966
6067import Control.Monad.Trans.Class (lift)
61−import Control.Monad.State (get, put)
68+import Data.ArrayBuffer.DataView (Endian(LE, BE))
69+import Data.ArrayBuffer.DataView (byteLength, byteOffset, get, part, buffer) as DV
70+import Data.ArrayBuffer.Types (DataView, Int16, Int32, Int8, Uint16, Uint32, Uint8, Float32, Float64, ByteLength)
71+import Data.ArrayBuffer.ValueMapping (class BytesPerType, class BinaryValue, class ShowArrayViewType, byteWidth)
72+import Data.Float32 as Float32
6273import Data.Maybe (Maybe(..))
63−import Data.Symbol (SProxy(..), class IsSymbol, reflectSymbol)
64−import Data.Tuple(Tuple(..))
74+import Data.Symbol (class IsSymbol)
75+import Data.Tuple (Tuple(..))
6576import Data.UInt (UInt)
66−import Data.Float32 as Float32
6777import Effect.Class (class MonadEffect, liftEffect)
78+import Parsing (ParseState(..), ParserT, Position(..), consume, fail, getParserT, stateParserT)
79+import Parsing.Combinators (tryRethrow)
6880import Type.Proxy (Proxy(..))
6981
70−import Text.Parsing.Parser (ParserT, ParseState(..), fail)
71−import Text.Parsing.Parser.Pos (Position(..))
72−import Text.Parsing.Parser.Combinators (tryRethrow)
73−import Data.ArrayBuffer.Types
74− ( DataView
75− , Int16
76− , Int32
77− , Int8
78− , Uint16
79− , Uint32
80− , Uint8
81− , Float32
82− , Float64
83− , ByteLength
84− )
85−import Data.ArrayBuffer.ValueMapping
86− ( class BytesPerType
87− , class BinaryValue
88− , class ShowArrayViewType
89− , byteWidth
90− )
91−import Data.ArrayBuffer.DataView
92− ( Endian(LE,BE)
93− )
94−import Data.ArrayBuffer.DataView (byteLength, byteOffset, get, part, buffer) as DV
95−
9682-- | Parse one fixed-bit-width `Data.ArrayBuffer.Types.ArrayViewType` primitive
9783-- | of a given endianness.
9884-- |
9985-- | #### Example
10086-- |
101−-- | Parse a little-endian 32-bit signed integer (4 bytes):
87+-- | Parse a little-endian 32-bit two’s-complement signed integer (4 bytes):
10288-- |
10389-- | anyPrim LE (Proxy :: Proxy Int32)
10490-- |
10591-- | or just use the convenience function `anyInt32le`, see below.
106−anyPrim :: forall a name m t
107− . BinaryValue a t
108− => BytesPerType a
109− => ShowArrayViewType a name
110− => IsSymbol name
111− => MonadEffect m
112− => Endian
113− -> Proxy a
114− -> ParserT DataView m t
92+anyPrim
93+ :: forall a name m t
94+ . BinaryValue a t
95+ => BytesPerType a
96+ => ShowArrayViewType a name
97+ => IsSymbol name
98+ => MonadEffect m
99+ => Endian
100+ -> Proxy a
101+ -> ParserT DataView m t
115102anyPrim endian _ = do
116− ParseState input (Position{line,column}) _ <- get
117− lift (liftEffect (DV.get endian (Proxy :: Proxy a) input (column-1))) >>= case _ of
118− Nothing -> fail $ "Cannot parse " <> reflectSymbol (SProxy :: SProxy name) <>
119− ", unexpected end of DataView"
103+ ParseState input (Position { index }) _ <- getParserT
104+ lift (liftEffect (DV.get endian (Proxy :: Proxy a) input index)) >>= case _ of
105+ Nothing -> fail "anyPrim unexpected end of DataView"
120106 Just i -> do
121− put $ ParseState input (Position {line, column:column + byteWidth (Proxy :: Proxy a) }) true
122− pure i
107+ stateParserT \_ -> Tuple i $ ParseState input (Position { line: 1, column: 1, index: index + byteWidth (Proxy :: Proxy a) }) true
123108
124−-- | Parse one 8-bit signed integer (byte).
109+-- | Parse one 8-bit two’s-complement signed integer (byte).
125110anyInt8 :: forall m. MonadEffect m => ParserT DataView m Int
126111anyInt8 = anyPrim LE (Proxy :: Proxy Int8)
127112
128−-- | Parse one 16-bit big-endian signed integer.
113+-- | Parse one 16-bit big-endian two’s-complement signed integer.
129114anyInt16be :: forall m. MonadEffect m => ParserT DataView m Int
130115anyInt16be = anyPrim BE (Proxy :: Proxy Int16)
131116
132−-- | Parse one 16-bit little-endian signed integer.
117+-- | Parse one 16-bit little-endian two’s-complement signed integer.
133118anyInt16le :: forall m. MonadEffect m => ParserT DataView m Int
134119anyInt16le = anyPrim LE (Proxy :: Proxy Int16)
135120
136−-- | Parse one 32-bit big-endian signed integer.
121+-- | Parse one 32-bit big-endian two’s-complement signed integer.
137122anyInt32be :: forall m. MonadEffect m => ParserT DataView m Int
138123anyInt32be = anyPrim BE (Proxy :: Proxy Int32)
139124
140−-- | Parse one 32-bit little-endian signed integer.
125+-- | Parse one 32-bit little-endian two’s-complement signed integer.
141126anyInt32le :: forall m. MonadEffect m => ParserT DataView m Int
142127anyInt32le = anyPrim LE (Proxy :: Proxy Int32)
143128
@@ -161,19 +146,19 @@ anyUint32be = anyPrim BE (Proxy :: Proxy Uint32)
161146anyUint32le :: forall m. MonadEffect m => ParserT DataView m UInt
162147anyUint32le = anyPrim LE (Proxy :: Proxy Uint32)
163148
164−-- | Parse one 32-bit big-endian floating point number.
149+-- | Parse one 32-bit big-endian IEEE 754 floating-point number.
165150anyFloat32be :: forall m. MonadEffect m => ParserT DataView m Float32.Float32
166151anyFloat32be = anyPrim BE (Proxy :: Proxy Float32)
167152
168−-- | Parse one 32-bit little-endian floating point number.
153+-- | Parse one 32-bit little-endian IEEE 754 floating-point number.
169154anyFloat32le :: forall m. MonadEffect m => ParserT DataView m Float32.Float32
170155anyFloat32le = anyPrim LE (Proxy :: Proxy Float32)
171156
172−-- | Parse one 64-bit big-endian floating point number.
157+-- | Parse one 64-bit big-endian IEEE 754 floating-point number.
173158anyFloat64be :: forall m. MonadEffect m => ParserT DataView m Number
174159anyFloat64be = anyPrim BE (Proxy :: Proxy Float64)
175160
176−-- | Parse one 64-bit little-endian floating point number.
161+-- | Parse one 64-bit little-endian IEEE 754 floating-point number.
177162anyFloat64le :: forall m. MonadEffect m => ParserT DataView m Number
178163anyFloat64le = anyPrim LE (Proxy :: Proxy Float64)
179164
@@ -186,22 +171,22 @@ anyFloat64le = anyPrim LE (Proxy :: Proxy Float64)
186171-- | satisfy LE (Proxy :: Proxy Int32) (_ == 3)
187172-- |
188173-- | or just use the convenience function `satisfyInt32le`, see below.
189−satisfy :: forall a name m t
190− . BinaryValue a t
191− => BytesPerType a
192− => ShowArrayViewType a name
193− => IsSymbol name
194− => Show t
195− => MonadEffect m
196− => Endian
197− -> Proxy a
198− -> (t -> Boolean)
199− -> ParserT DataView m t
174+satisfy
175+ :: forall a name m t
176+ . BinaryValue a t
177+ => BytesPerType a
178+ => ShowArrayViewType a name
179+ => IsSymbol name
180+ => Show t
181+ => MonadEffect m
182+ => Endian
183+ -> Proxy a
184+ -> (t -> Boolean)
185+ -> ParserT DataView m t
200186satisfy endian proxy f = tryRethrow do
201187 i <- anyPrim endian proxy
202188 if f i then pure i
203− else fail $ reflectSymbol (SProxy :: SProxy name) <>
204− " " <> show i <> " did not satisfy predicate."
189+ else fail "satisfy predicate failed"
205190
206191-- | Parse one 8-bit signed integer that satisfies the given predicate.
207192satisfyInt8 :: forall m. MonadEffect m => (Int -> Boolean) -> ParserT DataView m Int
@@ -270,29 +255,32 @@ satisfyFloat64le = satisfy LE (Proxy :: Proxy Float64)
270255-- |
271256takeN :: forall m. MonadEffect m => ByteLength -> ParserT DataView m DataView
272257takeN n = do
273− ParseState input (Position {line,column}) _ <- get
274− unless (n >= 0) $ fail $ "Cannot take negative number of bytes."
275− unless (column + n - 1 <= DV.byteLength input) $
276− fail $ "Cannot take " <> show n <> " bytes, only " <>
277− show (DV.byteLength input - column + 1) <> " bytes remain."
278− p <- lift $ liftEffect $ DV.part (DV.buffer input) (DV.byteOffset input + (column-1)) n
279− put $ ParseState input (Position {line,column:column+n}) true
280− pure p
258+ ParseState input (Position { index }) _ <- getParserT
259+ if (n < 0) then
260+ fail $ "takeN cannot take negative number of bytes"
261+ else if (index + n + 1 > DV.byteLength input) then
262+ fail "takeN expected N bytes"
263+ else do
264+ p <- lift $ liftEffect $ DV.part (DV.buffer input) (DV.byteOffset input + index) n
265+ stateParserT \_ -> Tuple p $ ParseState input (Position { line: 1, column: 1, index: index + n }) true
281266
282267-- | Take the rest of the input, however many bytes remain. Always succeeds.
283268takeRest :: forall m. MonadEffect m => ParserT DataView m DataView
284269takeRest = do
285− ParseState input (Position {line,column}) _ <- get
286− p <- lift $ liftEffect $ DV.part (DV.buffer input) (DV.byteOffset input + (column-1))
287− (DV.byteLength input - (column-1))
288− put $ ParseState input (Position {line,column:DV.byteLength input + 1}) true
289− pure p
270+ ParseState input (Position { index }) _ <- getParserT
271+ p <- lift $ liftEffect $ DV.part (DV.buffer input) (DV.byteOffset input + index)
272+ (DV.byteLength input - index)
273+ stateParserT \_ -> Tuple p $ ParseState input (Position { line: 1, column: 1, index: DV.byteLength input + 1 }) true
290274
291−-- | Parse succeeds at the end of the input DataView. Consumes no input.
275+-- | Parse succeeds at the end of the input DataView.
292276eof :: forall m. Monad m => ParserT DataView m Unit
293277eof = do
294− ParseState input (Position {column}) _ <- get
295− unless (column > DV.byteLength input) $ fail "Expected end of DataView"
278+ ParseState input (Position { index }) _ <- getParserT
279+ if (index + 1 > DV.byteLength input) then do
280+ -- We must consume so this combines correctly with notFollowedBy
281+ consume
282+ else do
283+ fail "eof expected end of DataView"
296284
297285-- | The
298286-- | [famous `match`](http://www.serpentine.com/blog/2014/05/31/attoparsec/#from-strings-to-buffers-and-cursors)
@@ -302,23 +290,22 @@ eof = do
302290-- | was consumed while it was being parsed.
303291match :: forall a m. MonadEffect m => ParserT DataView m a -> ParserT DataView m (Tuple DataView a)
304292match p = do
305− ParseState input (Position {column:column0}) _ <- get
293+ ParseState input (Position { index: index0 }) _ <- getParserT
306294 x <- p
307− ParseState _ (Position {column:column1}) _ <- get
308− part <- lift $ liftEffect $ DV.part (DV.buffer input) (DV.byteOffset input + (column0-1)) (column1-column0)
295+ ParseState _ (Position { index: index1 }) _ <- getParserT
296+ part <- lift $ liftEffect $ DV.part (DV.buffer input) (DV.byteOffset input + index0) (index1 - index0)
309297 pure $ Tuple part x
310298
311299-- ****************************** Notes ****************************************
312300--
313−-- The `initialPostion` in a `ParserT` is `Postion{line:1,column:1)`.
314−-- We keep `line` invariant and use `column-1` to denote the offset into the
315−-- `DataView`, that's why there are so many plus 1 and minus 1 operations
316−-- in this module.
317−-- https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html
318−--
319301-- We cannot have a primitive parser which parses a `DataView` and produces
320302-- an `ArrayView` (a Javascript Typed Array). Javascript DataViews are
321303-- endianess-aware, but Javascript Typed Arrays assume the native endianness
322304-- of the local machine. DataViews are intended to be used for I/O, ArrayViews
323305-- are intended to be used internally for graphics in a process, and they're
324306-- not intended to be both applied to the same ArrayBuffer.
307+-- The exception: `Uint8Array`
308+--
309+-- The failure messages are all constant strings form performance reasons.
310+-- If failure messages were constructed lazily then we could have more
311+-- descriptive messages.
test/Main.purs+25−18
@@ -7,17 +7,18 @@ import Data.ArrayBuffer.ArrayBuffer (empty) as AB
77import Data.ArrayBuffer.DataView as DataView
88import Data.Either (Either(..))
99import Data.List (fromFoldable)
10+import Data.List as List
1011import Data.Maybe (Maybe(..))
1112import Data.Traversable (for_)
1213import Data.Tuple (Tuple(..))
1314import Data.UInt (fromInt)
1415import Effect (Effect)
1516import Effect.Console (logShow)
16−import Test.Assert (assert')
17−import Text.Parsing.Parser (ParserT, runParserT, parseErrorPosition, fail)
18−import Text.Parsing.Parser.Combinators (manyTill)
19−import Text.Parsing.Parser.DataView as DV
20−import Text.Parsing.Parser.Pos (Position(..))
17+import Parsing (ParserT, Position(..), fail, parseErrorPosition, runParserT)
18+import Parsing.Combinators (many, manyTill)
19+import Parsing.DataView (anyInt8)
20+import Parsing.DataView as DV
21+import Test.Assert (assert', assertEqual')
2122
2223parseTestT :: forall s a. Show a => Eq a => s -> a -> ParserT s Effect a -> Effect Unit
2324parseTestT input expected p = do
@@ -32,19 +33,15 @@ parseFailT :: forall s a. s -> Position -> ParserT s Effect a -> Effect Unit
3233parseFailT input failPos p = do
3334 result <- runParserT input p
3435 case result of
35− Right _ -> assert' ("ParseError expected at " <> show failPos) false
36+ Right _ -> assert' ("ParseError expected at " <> show failPos) false
3637 Left err -> do
3738 let pos = parseErrorPosition err
3839 assert' ("ParseError expected at " <> show failPos <> " but parser failed at " <> show pos)
39− (pos == failPos)
40+ (pos == failPos)
4041 logShow $ show failPos
4142
4243mkPos :: Int -> Position
43−mkPos n = mkPos' n 1
44−
45−mkPos' :: Int -> Int -> Position
46−mkPos' column line = Position { column: column, line: line }
47−
44+mkPos n = Position { index: n, line: 1, column: 1 }
4845
4946main :: Effect Unit
5047main = do
@@ -52,13 +49,13 @@ main = do
5249 -- Test input is DataView = [5,6,7,8,9]
5350 ab <- AB.empty 5
5451 let dv = DataView.whole ab
55− for_ [0,1,2,3,4] $ \i -> DataView.setInt8 dv i (i+5)
52+ for_ [ 0, 1, 2, 3, 4 ] $ \i -> DataView.setInt8 dv i (i + 5)
5653 -- anyInt8
5754 parseTestT dv 5 DV.anyInt8
5855 -- manyTill eof
59− parseTestT dv (fromFoldable [5,6,7,8,9]) $ manyTill DV.anyInt8 DV.eof
56+ parseTestT dv (fromFoldable [ 5, 6, 7, 8, 9 ]) $ manyTill DV.anyInt8 DV.eof
6057 -- manyTill satisfy
61− parseTestT dv (fromFoldable [5,6,7,8]) $ manyTill DV.anyInt8 (DV.satisfyInt8 (_ == 9))
58+ parseTestT dv (fromFoldable [ 5, 6, 7, 8 ]) $ manyTill DV.anyInt8 (DV.satisfyInt8 (_ == 9))
6259 -- anyInt16be
6360 parseTestT dv 0x0506 DV.anyInt16be
6461 -- anyInt16le
@@ -68,7 +65,7 @@ main = do
6865 -- anyUint16le
6966 parseTestT dv (fromInt 0x0605) DV.anyUint16le
7067 -- fail on anyInt16le past end of DataView
71− parseFailT dv (mkPos 5) $ DV.anyInt16le *> DV.anyInt16le *> DV.anyInt16le
68+ parseFailT dv (mkPos 4) $ DV.anyInt16le *> DV.anyInt16le *> DV.anyInt16le
7269 -- anyInt32be and anyInt8
7370 parseTestT dv (Tuple 0x05060708 0x09) $ do
7471 l <- DV.anyInt32be
@@ -105,7 +102,7 @@ main = do
105102 Right actual -> pure actual
106103 Left err -> fail $ show err
107104 -- fail on takeN past end of DataView
108− parseFailT dv (mkPos 1) $ DV.takeN 6
105+ parseFailT dv (mkPos 0) $ DV.takeN 6
109106 -- takeRest then new parse on takeRest then anyInt8
110107 parseTestT dv 0x07 do
111108 _ <- DV.takeN 1
@@ -116,7 +113,7 @@ main = do
116113 Left err -> fail $ show err
117114 Right x -> pure x
118115 -- takeN then a new parse then fail on anyInt16le past end of DataView
119− parseFailT dv (mkPos 2) $ do
116+ parseFailT dv (mkPos 1) $ do
120117 dv2 <- DV.takeN 1
121118 lift (runParserT dv2 DV.anyInt16le) >>= case _ of
122119 Left err -> fail $ show err
@@ -130,3 +127,13 @@ main = do
130127 assert' ("match failed " <> show r0 <> " " <> show r1) $ r0 == Just 5 && r1 == Just 6
131128 logShow $ show r0 <> " " <> show r1
132129 Left err -> assert' ("match failed " <> show err) false
130+
131+ do
132+ ablarge <- AB.empty 200000
133+ let dvlarge = DataView.whole ablarge
134+ -- forE 0 (AB.byteLength ablarge - 1) \i -> void $ DataView.setInt8 dvlarge i i
135+ x <- map List.length <$> runParserT dvlarge (many anyInt8)
136+ assertEqual' "stack safety"
137+ { actual: x
138+ , expected: Right 200000
139+ }