@@ -15,13 +15,19 @@ module Streamly.Internal.Data.Binary.Decode
17 , word16be
17 , word16be
21import Control.Monad.Catch (MonadCatch, throwM)
26import Control.Monad.Catch (MonadCatch, throwM)
22import Data.Bits ((.|.), unsafeShiftL)
27import Data.Bits ((.|.), unsafeShiftL)
23−import Data.Word (Word8, Word16)
28+import Data.Word (Word8, Word16, Word32, Word64)
24import Streamly.Internal.Data.Parser (Parser)
29import Streamly.Internal.Data.Parser (Parser)
30+import Streamly.Internal.Data.Strict (Maybe'(..), Tuple' (..))
26import qualified Streamly.Internal.Data.Parser as PR
32import qualified Streamly.Internal.Data.Parser as PR
27import qualified Streamly.Internal.Data.Parser.ParserD as PRD
33import qualified Streamly.Internal.Data.Parser.ParserD as PRD
@@ -103,17 +109,16 @@ word16beD = PRD.Parser step initial extract
106− initial = return Nothing
112+ initial = return Nothing'
108− step Nothing a =
114+ step Nothing' a =
109 -- XXX We can use a non-failing parser or a fold so that we do not
115 -- XXX We can use a non-failing parser or a fold so that we do not
110 -- have to buffer for backtracking which is inefficient.
116 -- have to buffer for backtracking which is inefficient.
111− return $ PRD.Continue 0 (Just (fromIntegral a `unsafeShiftL` 8))
117+ return $ PRD.Continue 0 (Just' (fromIntegral a `unsafeShiftL` 8))
112− step (Just w) a =
118+ step (Just' w) a =
113 return $ PRD.Done 0 (w .|. fromIntegral a)
119 return $ PRD.Done 0 (w .|. fromIntegral a)
115− extract Nothing = throwM $ PRD.ParseError "word16beD: end of input"
121+ extract _ = throwM $ PRD.ParseError "word16be: end of input"
116− extract (Just _) = error "word16beD: unreachable state"
118-- | Parse two bytes as a 'Word16', the first byte is the MSB of the Word16 and
123-- | Parse two bytes as a 'Word16', the first byte is the MSB of the Word16 and
119-- second byte is the LSB (big endian representation).
124-- second byte is the LSB (big endian representation).
@@ -123,3 +128,134 @@ word16beD = PRD.Parser step initial extract
123{-# INLINE word16be #-}
128{-# INLINE word16be #-}
124word16be :: MonadCatch m => Parser m Word8 Word16
129word16be :: MonadCatch m => Parser m Word8 Word16
125word16be = PRK.toParserK word16beD
130word16be = PRK.toParserK word16beD
132+-- | Little endian (LSB first) Word16
133+{-# INLINE word16leD #-}
134+word16leD :: MonadCatch m => PRD.Parser m Word8 Word16
135+word16leD = PRD.Parser step initial extract
139+ initial = return Nothing'
142+ return $ PRD.Continue 0 (Just' (fromIntegral a))
144+ return $ PRD.Done 0 (w .|. fromIntegral a `unsafeShiftL` 8)
146+ extract _ = throwM $ PRD.ParseError "word16le: end of input"
148+-- | Parse two bytes as a 'Word16', the first byte is the LSB of the Word16 and
149+-- second byte is the MSB (little endian representation).
153+{-# INLINE word16le #-}
154+word16le :: MonadCatch m => Parser m Word8 Word16
155+word16le = PRK.toParserK word16leD
157+-- | Big endian (MSB first) Word32
158+{-# INLINE word32beD #-}
159+word32beD :: MonadCatch m => PRD.Parser m Word8 Word32
160+word32beD = PRD.Parser step initial extract
164+ initial = return $ Tuple' 0 24
166+ step (Tuple' w sh) a = return $
169+ let w1 = w .|. (fromIntegral a `unsafeShiftL` sh)
170+ in PRD.Continue 0 (Tuple' w1 (sh - 8))
171+ else PRD.Done 0 (w .|. fromIntegral a)
173+ extract _ = throwM $ PRD.ParseError "word32beD: end of input"
175+-- | Parse four bytes as a 'Word32', the first byte is the MSB of the Word32
176+-- and last byte is the LSB (big endian representation).
180+{-# INLINE word32be #-}
181+word32be :: MonadCatch m => Parser m Word8 Word32
182+word32be = PRK.toParserK word32beD
184+-- | Little endian (LSB first) Word32
185+{-# INLINE word32leD #-}
186+word32leD :: MonadCatch m => PRD.Parser m Word8 Word32
187+word32leD = PRD.Parser step initial extract
191+ initial = return $ Tuple' 0 0
193+ step (Tuple' w sh) a = return $
194+ let w1 = w .|. (fromIntegral a `unsafeShiftL` sh)
196+ then PRD.Continue 0 (Tuple' w1 (sh + 8))
199+ extract _ = throwM $ PRD.ParseError "word32leD: end of input"
201+-- | Parse four bytes as a 'Word32', the first byte is the MSB of the Word32
202+-- and last byte is the LSB (big endian representation).
206+{-# INLINE word32le #-}
207+word32le :: MonadCatch m => Parser m Word8 Word32
208+word32le = PRK.toParserK word32leD
210+-- | Big endian (MSB first) Word64
211+{-# INLINE word64beD #-}
212+word64beD :: MonadCatch m => PRD.Parser m Word8 Word64
213+word64beD = PRD.Parser step initial extract
217+ initial = return $ Tuple' 0 56
219+ step (Tuple' w sh) a = return $
222+ let w1 = w .|. (fromIntegral a `unsafeShiftL` sh)
223+ in PRD.Continue 0 (Tuple' w1 (sh - 8))
224+ else PRD.Done 0 (w .|. fromIntegral a)
226+ extract _ = throwM $ PRD.ParseError "word64beD: end of input"
228+-- | Parse eight bytes as a 'Word64', the first byte is the MSB of the Word64
229+-- and last byte is the LSB (big endian representation).
233+{-# INLINE word64be #-}
234+word64be :: MonadCatch m => Parser m Word8 Word64
235+word64be = PRK.toParserK word64beD
237+-- | Little endian (LSB first) Word64
238+{-# INLINE word64leD #-}
239+word64leD :: MonadCatch m => PRD.Parser m Word8 Word64
240+word64leD = PRD.Parser step initial extract
244+ initial = return $ Tuple' 0 0
246+ step (Tuple' w sh) a = return $
247+ let w1 = w .|. (fromIntegral a `unsafeShiftL` sh)
249+ then PRD.Continue 0 (Tuple' w1 (sh + 8))
252+ extract _ = throwM $ PRD.ParseError "word64leD: end of input"
254+-- | Parse eight bytes as a 'Word64', the first byte is the MSB of the Word64
255+-- and last byte is the LSB (big endian representation).
259+{-# INLINE word64le #-}
260+word64le :: MonadCatch m => Parser m Word8 Word64
261+word64le = PRK.toParserK word64leD