@@ -0,0 +1,261 @@
2+-- Module : Streamly.Internal.Data.Binary.Encode
3+-- Copyright : (c) 2022 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : pre-release
9+-- Converting Haskell data types to byte streams.
11+module Streamly.Internal.Data.Binary.Encode
28+import Data.Bits (shiftR)
29+import Data.Word (Word8, Word16, Word32, Word64)
30+import Streamly.Internal.Data.Stream (Stream, fromStreamD)
31+import Streamly.Internal.Data.Stream.StreamD (Step(..))
33+import qualified Streamly.Data.Stream as Stream
34+import qualified Streamly.Internal.Data.Stream.StreamD as D
36+-- XXX Use StreamD directly?
38+-- | A value of type '()' is encoded as @0@ in binary encoding.
47+unit :: Stream m Word8
48+unit = Stream.fromPure 0
50+{-# INLINE boolToWord8 #-}
51+boolToWord8 :: Bool -> Word8
55+-- | A value of type 'Bool' is encoded as follows in binary encoding.
65+bool :: Bool -> Stream m Word8
66+bool = Stream.fromPure . boolToWord8
68+{-# INLINE orderingToWord8 #-}
69+orderingToWord8 :: Ordering -> Word8
70+orderingToWord8 LT = 0
71+orderingToWord8 EQ = 1
72+orderingToWord8 GT = 2
74+-- | A value of type 'Ordering' is encoded as follows in binary encoding.
84+{-# INLINE ordering #-}
85+ordering :: Ordering -> Stream m Word8
86+ordering = Stream.fromPure . orderingToWord8
88+-- | Stream a 'Word8'.
93+word8 :: Word8 -> Stream m Word8
94+word8 = Stream.fromPure
96+data W16State = W16B1 | W16B2 | W16Done
98+{-# INLINE word16beD #-}
99+word16beD :: Applicative m => Word16 -> D.Stream m Word8
100+word16beD w = D.Stream step W16B1
104+ step _ W16B1 = pure $ Yield (fromIntegral (shiftR w 8) :: Word8) W16B2
105+ step _ W16B2 = pure $ Yield (fromIntegral w :: Word8) W16Done
106+ step _ W16Done = pure Stop
108+-- | Stream a 'Word16' as two bytes, the first byte is the MSB of the Word16
109+-- and second byte is the LSB (big endian representation).
113+{-# INLINE word16be #-}
114+word16be :: Monad m => Word16 -> Stream m Word8
115+word16be = fromStreamD . word16beD
117+-- | Little endian (LSB first) Word16
118+{-# INLINE word16leD #-}
119+word16leD :: Applicative m => Word16 -> D.Stream m Word8
120+word16leD w = D.Stream step W16B1
124+ step _ W16B1 = pure $ Yield (fromIntegral w :: Word8) W16B2
125+ step _ W16B2 = pure $ Yield (fromIntegral (shiftR w 8) :: Word8) W16Done
126+ step _ W16Done = pure Stop
128+-- | Stream a 'Word16' as two bytes, the first byte is the LSB of the Word16
129+-- and second byte is the MSB (little endian representation).
133+{-# INLINE word16le #-}
134+word16le :: Monad m => Word16 -> Stream m Word8
135+word16le = fromStreamD . word16leD
137+data W32State = W32B1 | W32B2 | W32B3 | W32B4 | W32Done
139+-- | Big endian (MSB first) Word32
140+{-# INLINE word32beD #-}
141+word32beD :: Applicative m => Word32 -> D.Stream m Word8
142+word32beD w = D.Stream step W32B1
146+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
148+ step _ W32B1 = yield 24 W32B2
149+ step _ W32B2 = yield 16 W32B3
150+ step _ W32B3 = yield 8 W32B4
151+ step _ W32B4 = pure $ Yield (fromIntegral w :: Word8) W32Done
152+ step _ W32Done = pure Stop
154+-- | Stream a 'Word32' as four bytes, the first byte is the MSB of the Word32
155+-- and last byte is the LSB (big endian representation).
159+{-# INLINE word32be #-}
160+word32be :: Monad m => Word32 -> Stream m Word8
161+word32be = fromStreamD . word32beD
163+-- | Little endian (LSB first) Word32
164+{-# INLINE word32leD #-}
165+word32leD :: Applicative m => Word32 -> D.Stream m Word8
166+word32leD w = D.Stream step W32B1
170+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
172+ step _ W32B1 = pure $ Yield (fromIntegral w :: Word8) W32B2
173+ step _ W32B2 = yield 8 W32B3
174+ step _ W32B3 = yield 16 W32B4
175+ step _ W32B4 = yield 24 W32Done
176+ step _ W32Done = pure Stop
178+-- | Stream a 'Word32' as four bytes, the first byte is the MSB of the Word32
179+-- and last byte is the LSB (big endian representation).
183+{-# INLINE word32le #-}
184+word32le :: Monad m => Word32 -> Stream m Word8
185+word32le = fromStreamD . word32leD
188+ W64B1 | W64B2 | W64B3 | W64B4 | W64B5 | W64B6 | W64B7 | W64B8 | W64Done
190+-- | Big endian (MSB first) Word64
191+{-# INLINE word64beD #-}
192+word64beD :: Applicative m => Word64 -> D.Stream m Word8
193+word64beD w = D.Stream step W64B1
197+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
199+ step _ W64B1 = yield 56 W64B2
200+ step _ W64B2 = yield 48 W64B3
201+ step _ W64B3 = yield 40 W64B4
202+ step _ W64B4 = yield 32 W64B5
203+ step _ W64B5 = yield 24 W64B6
204+ step _ W64B6 = yield 16 W64B7
205+ step _ W64B7 = yield 8 W64B8
206+ step _ W64B8 = pure $ Yield (fromIntegral w :: Word8) W64Done
207+ step _ W64Done = pure Stop
209+-- | Stream a 'Word64' as eight bytes, the first byte is the MSB of the Word64
210+-- and last byte is the LSB (big endian representation).
214+{-# INLINE word64be #-}
215+word64be :: Monad m => Word64 -> Stream m Word8
216+word64be = fromStreamD . word64beD
218+-- | Little endian (LSB first) Word64
219+{-# INLINE word64leD #-}
220+word64leD :: Applicative m => Word64 -> D.Stream m Word8
221+word64leD w = D.Stream step W64B1
225+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
227+ step _ W64B1 = pure $ Yield (fromIntegral w :: Word8) W64B2
228+ step _ W64B2 = yield 8 W64B3
229+ step _ W64B3 = yield 16 W64B4
230+ step _ W64B4 = yield 24 W64B5
231+ step _ W64B5 = yield 32 W64B6
232+ step _ W64B6 = yield 40 W64B7
233+ step _ W64B7 = yield 48 W64B8
234+ step _ W64B8 = yield 56 W64Done
235+ step _ W64Done = pure Stop
237+-- | Stream a 'Word64' as eight bytes, the first byte is the MSB of the Word64
238+-- and last byte is the LSB (big endian representation).
242+{-# INLINE word64le #-}
243+word64le :: Monad m => Word64 -> Stream m Word8
244+word64le = fromStreamD . word64leD
246+-------------------------------------------------------------------------------
248+-------------------------------------------------------------------------------
250+-- | Stream a 'Word64' as eight bytes in the host byte order.
254+{-# INLINE word64host #-}
255+word64host :: Monad m => Word64 -> Stream m Word8
257+#ifdef WORDS_BIGENDIAN