on master help sign in
Add Word16 LE, Word32 and Word64 parsers
commit0f5404dfc6ea3c7d818f17aac80d62feb14102e8 authorHarendra Kumar <harendra@composewell.com> dateFri 7 Aug 2020, 23:54 (6 years ago) parent8a3828a
1 file changed+143−7
src/Streamly/Internal/Data/Binary/Decode.hs+143−7
src/Streamly/Internal/Data/Binary/Decode.hs+143−7
@@ -15,13 +15,19 @@ module Streamly.Internal.Data.Binary.Decode
1515 , eqWord8
1616 , word8
1717 , word16be
18+ , word16le
19+ , word32be
20+ , word32le
21+ , word64be
22+ , word64le
1823 )
1924where
2025
2126import Control.Monad.Catch (MonadCatch, throwM)
2227import Data.Bits ((.|.), unsafeShiftL)
23−import Data.Word (Word8, Word16)
28+import Data.Word (Word8, Word16, Word32, Word64)
2429import Streamly.Internal.Data.Parser (Parser)
30+import Streamly.Internal.Data.Strict (Maybe'(..), Tuple' (..))
2531
2632import qualified Streamly.Internal.Data.Parser as PR
2733import qualified Streamly.Internal.Data.Parser.ParserD as PRD
@@ -103,17 +109,16 @@ word16beD = PRD.Parser step initial extract
103109
104110 where
105111
106− initial = return Nothing
112+ initial = return Nothing'
107113
108− step Nothing a =
114+ step Nothing' a =
109115 -- XXX We can use a non-failing parser or a fold so that we do not
110116 -- have to buffer for backtracking which is inefficient.
111− return $ PRD.Continue 0 (Just (fromIntegral a `unsafeShiftL` 8))
112− step (Just w) a =
117+ return $ PRD.Continue 0 (Just' (fromIntegral a `unsafeShiftL` 8))
118+ step (Just' w) a =
113119 return $ PRD.Done 0 (w .|. fromIntegral a)
114120
115− extract Nothing = throwM $ PRD.ParseError "word16beD: end of input"
116− extract (Just _) = error "word16beD: unreachable state"
121+ extract _ = throwM $ PRD.ParseError "word16be: end of input"
117122
118123-- | Parse two bytes as a 'Word16', the first byte is the MSB of the Word16 and
119124-- second byte is the LSB (big endian representation).
@@ -123,3 +128,134 @@ word16beD = PRD.Parser step initial extract
123128{-# INLINE word16be #-}
124129word16be :: MonadCatch m => Parser m Word8 Word16
125130word16be = PRK.toParserK word16beD
131+
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
136+
137+ where
138+
139+ initial = return Nothing'
140+
141+ step Nothing' a =
142+ return $ PRD.Continue 0 (Just' (fromIntegral a))
143+ step (Just' w) a =
144+ return $ PRD.Done 0 (w .|. fromIntegral a `unsafeShiftL` 8)
145+
146+ extract _ = throwM $ PRD.ParseError "word16le: end of input"
147+
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).
150+--
151+-- /Internal/
152+--
153+{-# INLINE word16le #-}
154+word16le :: MonadCatch m => Parser m Word8 Word16
155+word16le = PRK.toParserK word16leD
156+
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
161+
162+ where
163+
164+ initial = return $ Tuple' 0 24
165+
166+ step (Tuple' w sh) a = return $
167+ if sh /= 0
168+ then
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)
172+
173+ extract _ = throwM $ PRD.ParseError "word32beD: end of input"
174+
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).
177+--
178+-- /Internal/
179+--
180+{-# INLINE word32be #-}
181+word32be :: MonadCatch m => Parser m Word8 Word32
182+word32be = PRK.toParserK word32beD
183+
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
188+
189+ where
190+
191+ initial = return $ Tuple' 0 0
192+
193+ step (Tuple' w sh) a = return $
194+ let w1 = w .|. (fromIntegral a `unsafeShiftL` sh)
195+ in if sh /= 24
196+ then PRD.Continue 0 (Tuple' w1 (sh + 8))
197+ else PRD.Done 0 w1
198+
199+ extract _ = throwM $ PRD.ParseError "word32leD: end of input"
200+
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).
203+--
204+-- /Internal/
205+--
206+{-# INLINE word32le #-}
207+word32le :: MonadCatch m => Parser m Word8 Word32
208+word32le = PRK.toParserK word32leD
209+
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
214+
215+ where
216+
217+ initial = return $ Tuple' 0 56
218+
219+ step (Tuple' w sh) a = return $
220+ if sh /= 0
221+ then
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)
225+
226+ extract _ = throwM $ PRD.ParseError "word64beD: end of input"
227+
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).
230+--
231+-- /Internal/
232+--
233+{-# INLINE word64be #-}
234+word64be :: MonadCatch m => Parser m Word8 Word64
235+word64be = PRK.toParserK word64beD
236+
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
241+
242+ where
243+
244+ initial = return $ Tuple' 0 0
245+
246+ step (Tuple' w sh) a = return $
247+ let w1 = w .|. (fromIntegral a `unsafeShiftL` sh)
248+ in if sh /= 56
249+ then PRD.Continue 0 (Tuple' w1 (sh + 8))
250+ else PRD.Done 0 w1
251+
252+ extract _ = throwM $ PRD.ParseError "word64leD: end of input"
253+
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).
256+--
257+-- /Internal/
258+--
259+{-# INLINE word64le #-}
260+word64le :: MonadCatch m => Parser m Word8 Word64
261+word64le = PRK.toParserK word64leD