on master help sign in
Add the Binary encoding module
commit0a7a664796a6ebf7dcd7ba7f2fd59303ab834eb8 authorHarendra Kumar <harendra@composewell.com> dateFri 16 Dec 2022, 06:33 (4 years ago) parent7de3189
2 files changed+262
core/src/Streamly/Internal/Data/Binary/Encode.hs+261 core/streamly-core.cabal+1
core/src/Streamly/Internal/Data/Binary/Encode.hsnew file+261
@@ -0,0 +1,261 @@
1+-- |
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
7+-- Portability : GHC
8+--
9+-- Converting Haskell data types to byte streams.
10+
11+module Streamly.Internal.Data.Binary.Encode
12+ ( unit
13+ , bool
14+ , ordering
15+ , word8
16+ , word16be
17+ , word16le
18+ , word32be
19+ , word32le
20+ , word64be
21+ , word64le
22+ , word64host
23+ )
24+where
25+
26+#include "MachDeps.h"
27+
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(..))
32+
33+import qualified Streamly.Data.Stream as Stream
34+import qualified Streamly.Internal.Data.Stream.StreamD as D
35+
36+-- XXX Use StreamD directly?
37+
38+-- | A value of type '()' is encoded as @0@ in binary encoding.
39+--
40+-- @
41+-- 0 ==> ()
42+-- @
43+--
44+-- /Pre-release/
45+--
46+{-# INLINE unit #-}
47+unit :: Stream m Word8
48+unit = Stream.fromPure 0
49+
50+{-# INLINE boolToWord8 #-}
51+boolToWord8 :: Bool -> Word8
52+boolToWord8 False = 0
53+boolToWord8 True = 1
54+
55+-- | A value of type 'Bool' is encoded as follows in binary encoding.
56+--
57+-- @
58+-- 0 ==> False
59+-- 1 ==> True
60+-- @
61+--
62+-- /Pre-release/
63+--
64+{-# INLINE bool #-}
65+bool :: Bool -> Stream m Word8
66+bool = Stream.fromPure . boolToWord8
67+
68+{-# INLINE orderingToWord8 #-}
69+orderingToWord8 :: Ordering -> Word8
70+orderingToWord8 LT = 0
71+orderingToWord8 EQ = 1
72+orderingToWord8 GT = 2
73+
74+-- | A value of type 'Ordering' is encoded as follows in binary encoding.
75+--
76+-- @
77+-- 0 ==> LT
78+-- 1 ==> EQ
79+-- 2 ==> GT
80+-- @
81+--
82+-- /Pre-release/
83+--
84+{-# INLINE ordering #-}
85+ordering :: Ordering -> Stream m Word8
86+ordering = Stream.fromPure . orderingToWord8
87+
88+-- | Stream a 'Word8'.
89+--
90+-- /Pre-release/
91+--
92+{-# INLINE word8 #-}
93+word8 :: Word8 -> Stream m Word8
94+word8 = Stream.fromPure
95+
96+data W16State = W16B1 | W16B2 | W16Done
97+
98+{-# INLINE word16beD #-}
99+word16beD :: Applicative m => Word16 -> D.Stream m Word8
100+word16beD w = D.Stream step W16B1
101+
102+ where
103+
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
107+
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).
110+--
111+-- /Pre-release/
112+--
113+{-# INLINE word16be #-}
114+word16be :: Monad m => Word16 -> Stream m Word8
115+word16be = fromStreamD . word16beD
116+
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
121+
122+ where
123+
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
127+
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).
130+--
131+-- /Pre-release/
132+--
133+{-# INLINE word16le #-}
134+word16le :: Monad m => Word16 -> Stream m Word8
135+word16le = fromStreamD . word16leD
136+
137+data W32State = W32B1 | W32B2 | W32B3 | W32B4 | W32Done
138+
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
143+
144+ where
145+
146+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
147+
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
153+
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).
156+--
157+-- /Pre-release/
158+--
159+{-# INLINE word32be #-}
160+word32be :: Monad m => Word32 -> Stream m Word8
161+word32be = fromStreamD . word32beD
162+
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
167+
168+ where
169+
170+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
171+
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
177+
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).
180+--
181+-- /Pre-release/
182+--
183+{-# INLINE word32le #-}
184+word32le :: Monad m => Word32 -> Stream m Word8
185+word32le = fromStreamD . word32leD
186+
187+data W64State =
188+ W64B1 | W64B2 | W64B3 | W64B4 | W64B5 | W64B6 | W64B7 | W64B8 | W64Done
189+
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
194+
195+ where
196+
197+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
198+
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
208+
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).
211+--
212+-- /Pre-release/
213+--
214+{-# INLINE word64be #-}
215+word64be :: Monad m => Word64 -> Stream m Word8
216+word64be = fromStreamD . word64beD
217+
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
222+
223+ where
224+
225+ yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
226+
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
236+
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).
239+--
240+-- /Pre-release/
241+--
242+{-# INLINE word64le #-}
243+word64le :: Monad m => Word64 -> Stream m Word8
244+word64le = fromStreamD . word64leD
245+
246+-------------------------------------------------------------------------------
247+-- Host byte order
248+-------------------------------------------------------------------------------
249+
250+-- | Stream a 'Word64' as eight bytes in the host byte order.
251+--
252+-- /Pre-release/
253+--
254+{-# INLINE word64host #-}
255+word64host :: Monad m => Word64 -> Stream m Word8
256+word64host =
257+#ifdef WORDS_BIGENDIAN
258+ word64be
259+#else
260+ word64le
261+#endif
core/streamly-core.cabal+1
@@ -335,6 +335,7 @@ library
335335
336336 -- streamly-serde
337337 , Streamly.Internal.Data.Binary.Decode
338+ , Streamly.Internal.Data.Binary.Encode
338339
339340 -- streamly-unicode-core
340341 , Streamly.Internal.Unicode.Stream