@@ -24,6 +24,7 @@ import Control.Monad.Trans.Class (lift)
2424import Data.Array (snoc , foldRecM )
2525import Data.Array as Array
2626import Data.ArrayBuffer.Builder (DataBuff (..), PutM , subBuilder )
27+ import Data.ArrayBuffer.DataView (byteLength )
2728import Data.ArrayBuffer.Types (DataView , ByteLength )
2829import Data.Enum (class BoundedEnum , fromEnum , toEnum )
2930import Data.Foldable (foldl )
@@ -39,7 +40,8 @@ import Data.UInt64 (UInt64)
3940import Data.UInt64 as UInt64
4041import Effect.Class (class MonadEffect )
4142import Parsing (ParserT , Position (..), fail , position )
42- import Parsing.DataView (takeN )
43+ import Parsing.Combinators (lookAhead )
44+ import Parsing.DataView (takeN , takeRest )
4345import Protobuf.Internal.Common (Bytes (..), FieldNumber , WireType (..), label )
4446import Protobuf.Internal.Decode as Decode
4547import Protobuf.Internal.Encode as Encode
@@ -76,6 +78,7 @@ type FieldNumberInt
7678 = Int
7779
7880-- | Call a parser repeatedly until exactly *N* bytes have been consumed.
81+ -- | Will fail if not enough bytes remain in the DataView.
7982-- | Will fail if too many bytes are consumed.
8083manyLength ::
8184 forall m a .
@@ -85,19 +88,24 @@ manyLength ::
8588 ByteLength ->
8689 ParserT DataView m (Array a )
8790manyLength p len = do
88- Position { index: posBegin } <- position
89- let
90- go :: List a -> ParserT DataView m (Step (List a ) (List a ))
91- go accum = do
92- Position { index: pos } <- position
93- case compare (pos - posBegin) len of
94- GT -> fail " manyLength consumed too many bytes."
95- EQ -> lift $ pure (Done accum)
96- LT -> do
97- x <- p
98- pure (Loop (x : accum))
99- -- https://github.com/purescript-contrib/purescript-parsing/pull/199#issuecomment-1145956271
100- Array .reverse <$> Array .fromFoldable <$> tailRecM go List.Nil
91+ remaining_bytes :: Int <- byteLength <$> lookAhead takeRest
92+ if remaining_bytes < len
93+ then do
94+ fail $ " manyLength " <> show len <> " not enough bytes of input " <> show remaining_bytes <> " remaining"
95+ else do
96+ Position { index: posBegin } <- position
97+ let
98+ go :: List a -> ParserT DataView m (Step (List a ) (List a ))
99+ go accum = do
100+ Position { index: pos } <- position
101+ case compare (pos - posBegin) len of
102+ GT -> fail $ " manyLength " <> show len <> " consumed too many bytes " <> (show $ pos - posBegin)
103+ EQ -> lift $ pure (Done accum)
104+ LT -> do
105+ x <- p
106+ pure (Loop (x : accum))
107+ -- https://github.com/purescript-contrib/purescript-parsing/pull/199#issuecomment-1145956271
108+ Array .reverse <$> Array .fromFoldable <$> tailRecM go List.Nil
101109
102110-- | A message field value from an unknown `.proto` definition.
103111-- |
@@ -174,13 +182,20 @@ putFieldUnknown (UnknownLenDel fieldNumber x) = Encode.encodeBytesField fieldNum
174182
175183putFieldUnknown (UnknownBits32 fieldNumber x) = Encode .encodeBytesField fieldNumber x
176184
177- -- | Parse a length , then call a parser which takes one length as its argument.
185+ -- | Parse a bytelength , then call a parser which takes one bytelength as its argument.
178186parseLenDel ::
179187 forall m a .
180188 MonadEffect m =>
181189 (Int -> ParserT DataView m a ) ->
182190 ParserT DataView m a
183- parseLenDel p = p <<< UInt .toInt =<< Decode .decodeVarint32
191+ parseLenDel p = do
192+ len <- UInt .toInt <$> Decode .decodeVarint32
193+ remaining_bytes :: Int <- byteLength <$> lookAhead takeRest
194+ if remaining_bytes < len
195+ then do
196+ fail $ " parseLenDel " <> show len <> " not enough bytes of input " <> show remaining_bytes <> " remaining"
197+ else do
198+ p len
184199
185200putLenDel ::
186201 forall m a .
0 commit comments