2-- Module : Streamly.Internal.Serialize.ToBytes
3-- Copyright : (c) 2022 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
8-- Encode Haskell data types to byte streams.
10-- The primary purpose of this module is to serialize primitive Haskell types
11-- to streams for convenient byte by byte processing when such a need arises.
13-- It would be inefficient to use this to build byte streams from algebraic
14-- data types. For general serialization of ADTs please use the Serialize type
15-- class instances. The fastest way to convert general Haskell types to byte
16-- streams is to serialize them to an array and then stream the array.
18-- XXX remove unit, bool, ordering, and the type class as well
20module Streamly.Internal.Serialize.ToBytes
55import Data.Bits (shiftR)
57import Data.Int (Int8, Int16, Int32, Int64)
58import Data.Word (Word8, Word16, Word32, Word64)
59import GHC.Float (castDoubleToWord64, castFloatToWord32)
60import Streamly.Internal.Data.Stream (Stream)
61import Streamly.Internal.Data.Stream (Step(..))
62import Streamly.Internal.Unicode.Stream (readCharUtf8)
64import qualified Streamly.Internal.Data.Stream as Stream
65import qualified Streamly.Internal.Data.Stream as D
67-- XXX Use StreamD directly?
69-- | A value of type '()' is encoded as @0@ in binary encoding.
78unit :: Applicative m => Stream m Word8
79unit = Stream.fromPure 0
81{-# INLINE boolToWord8 #-}
82boolToWord8 :: Bool -> Word8
86-- | A value of type 'Bool' is encoded as follows in binary encoding.
96bool :: Applicative m => Bool -> Stream m Word8
97bool = Stream.fromPure . boolToWord8
99{-# INLINE orderingToWord8 #-}
100orderingToWord8 :: Ordering -> Word8
101orderingToWord8 LT = 0
102orderingToWord8 EQ = 1
103orderingToWord8 GT = 2
105-- | A value of type 'Ordering' is encoded as follows in binary encoding.
115{-# INLINE ordering #-}
116ordering :: Applicative m => Ordering -> Stream m Word8
117ordering = Stream.fromPure . orderingToWord8
119-- | Stream a 'Word8'.
124word8 :: Applicative m => Word8 -> Stream m Word8
125word8 = Stream.fromPure
127data W16State = W16B1 | W16B2 | W16Done
129{-# INLINE word16beD #-}
130word16beD :: Applicative m => Word16 -> D.Stream m Word8
131word16beD w = D.Stream step W16B1
135 step _ W16B1 = pure $ Yield (fromIntegral (shiftR w 8) :: Word8) W16B2
136 step _ W16B2 = pure $ Yield (fromIntegral w :: Word8) W16Done
137 step _ W16Done = pure Stop
139-- | Stream a 'Word16' as two bytes, the first byte is the MSB of the Word16
140-- and second byte is the LSB (big endian representation).
144{-# INLINE word16be #-}
145word16be :: Monad m => Word16 -> Stream m Word8
148-- | Little endian (LSB first) Word16
149{-# INLINE word16leD #-}
150word16leD :: Applicative m => Word16 -> D.Stream m Word8
151word16leD w = D.Stream step W16B1
155 step _ W16B1 = pure $ Yield (fromIntegral w :: Word8) W16B2
156 step _ W16B2 = pure $ Yield (fromIntegral (shiftR w 8) :: Word8) W16Done
157 step _ W16Done = pure Stop
159-- | Stream a 'Word16' as two bytes, the first byte is the LSB of the Word16
160-- and second byte is the MSB (little endian representation).
164{-# INLINE word16le #-}
165word16le :: Monad m => Word16 -> Stream m Word8
168data W32State = W32B1 | W32B2 | W32B3 | W32B4 | W32Done
170-- | Big endian (MSB first) Word32
171{-# INLINE word32beD #-}
172word32beD :: Applicative m => Word32 -> D.Stream m Word8
173word32beD w = D.Stream step W32B1
177 yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
179 step _ W32B1 = yield 24 W32B2
180 step _ W32B2 = yield 16 W32B3
181 step _ W32B3 = yield 8 W32B4
182 step _ W32B4 = pure $ Yield (fromIntegral w :: Word8) W32Done
183 step _ W32Done = pure Stop
185-- | Stream a 'Word32' as four bytes, the first byte is the MSB of the Word32
186-- and last byte is the LSB (big endian representation).
190{-# INLINE word32be #-}
191word32be :: Monad m => Word32 -> Stream m Word8
194-- | Little endian (LSB first) Word32
195{-# INLINE word32leD #-}
196word32leD :: Applicative m => Word32 -> D.Stream m Word8
197word32leD w = D.Stream step W32B1
201 yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
203 step _ W32B1 = pure $ Yield (fromIntegral w :: Word8) W32B2
204 step _ W32B2 = yield 8 W32B3
205 step _ W32B3 = yield 16 W32B4
206 step _ W32B4 = yield 24 W32Done
207 step _ W32Done = pure Stop
209-- | Stream a 'Word32' as four bytes, the first byte is the MSB of the Word32
210-- and last byte is the LSB (big endian representation).
214{-# INLINE word32le #-}
215word32le :: Monad m => Word32 -> Stream m Word8
219 W64B1 | W64B2 | W64B3 | W64B4 | W64B5 | W64B6 | W64B7 | W64B8 | W64Done
221-- | Big endian (MSB first) Word64
222{-# INLINE word64beD #-}
223word64beD :: Applicative m => Word64 -> D.Stream m Word8
224word64beD w = D.Stream step W64B1
228 yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
230 step _ W64B1 = yield 56 W64B2
231 step _ W64B2 = yield 48 W64B3
232 step _ W64B3 = yield 40 W64B4
233 step _ W64B4 = yield 32 W64B5
234 step _ W64B5 = yield 24 W64B6
235 step _ W64B6 = yield 16 W64B7
236 step _ W64B7 = yield 8 W64B8
237 step _ W64B8 = pure $ Yield (fromIntegral w :: Word8) W64Done
238 step _ W64Done = pure Stop
240-- | Stream a 'Word64' as eight bytes, the first byte is the MSB of the Word64
241-- and last byte is the LSB (big endian representation).
245{-# INLINE word64be #-}
246word64be :: Monad m => Word64 -> Stream m Word8
249-- | Little endian (LSB first) Word64
250{-# INLINE word64leD #-}
251word64leD :: Applicative m => Word64 -> D.Stream m Word8
252word64leD w = D.Stream step W64B1
256 yield n s = pure $ Yield (fromIntegral (shiftR w n) :: Word8) s
258 step _ W64B1 = pure $ Yield (fromIntegral w :: Word8) W64B2
259 step _ W64B2 = yield 8 W64B3
260 step _ W64B3 = yield 16 W64B4
261 step _ W64B4 = yield 24 W64B5
262 step _ W64B5 = yield 32 W64B6
263 step _ W64B6 = yield 40 W64B7
264 step _ W64B7 = yield 48 W64B8
265 step _ W64B8 = yield 56 W64Done
266 step _ W64Done = pure Stop
268-- | Stream a 'Word64' as eight bytes, the first byte is the MSB of the Word64
269-- and last byte is the LSB (big endian representation).
273{-# INLINE word64le #-}
274word64le :: Monad m => Word64 -> Stream m Word8
278int8 :: Applicative m => Int8 -> Stream m Word8
279int8 i = word8 (fromIntegral i :: Word8)
281-- | Stream a 'Int16' as two bytes, the first byte is the MSB of the Int16
282-- and second byte is the LSB (big endian representation).
286{-# INLINE int16be #-}
287int16be :: Monad m => Int16 -> Stream m Word8
288int16be i = word16be (fromIntegral i :: Word16)
290-- | Stream a 'Int16' as two bytes, the first byte is the LSB of the Int16
291-- and second byte is the MSB (little endian representation).
295{-# INLINE int16le #-}
296int16le :: Monad m => Int16 -> Stream m Word8
297int16le i = word16le (fromIntegral i :: Word16)
299-- | Stream a 'Int32' as four bytes, the first byte is the MSB of the Int32
300-- and last byte is the LSB (big endian representation).
304{-# INLINE int32be #-}
305int32be :: Monad m => Int32 -> Stream m Word8
306int32be i = word32be (fromIntegral i :: Word32)
308{-# INLINE int32le #-}
309int32le :: Monad m => Int32 -> Stream m Word8
310int32le i = word32le (fromIntegral i :: Word32)
312-- | Stream a 'Int64' as eight bytes, the first byte is the MSB of the Int64
313-- and last byte is the LSB (big endian representation).
317{-# INLINE int64be #-}
318int64be :: Monad m => Int64 -> Stream m Word8
319int64be i = word64be (fromIntegral i :: Word64)
321-- | Stream a 'Int64' as eight bytes, the first byte is the LSB of the Int64
322-- and last byte is the MSB (little endian representation).
326{-# INLINE int64le #-}
327int64le :: Monad m => Int64 -> Stream m Word8
328int64le i = word64le (fromIntegral i :: Word64)
330-- | Big endian (MSB first) Float
331{-# INLINE float32be #-}
332float32be :: Monad m => Float -> Stream m Word8
333float32be = word32beD . castFloatToWord32
335-- | Little endian (LSB first) Float
336{-# INLINE float32le #-}
337float32le :: Monad m => Float -> Stream m Word8
338float32le = word32leD . castFloatToWord32
340-- | Big endian (MSB first) Double
341{-# INLINE double64be #-}
342double64be :: Monad m => Double -> Stream m Word8
343double64be = word64beD . castDoubleToWord64
345-- | Little endian (LSB first) Double
346{-# INLINE double64le #-}
347double64le :: Monad m => Double -> Stream m Word8
348double64le = word64leD . castDoubleToWord64
350-- | Encode a Unicode character to stream of bytes in 0-255 range.
352{-# INLINE charLatin1 #-}
353charLatin1 :: Applicative m => Char -> Stream m Word8
354charLatin1 = Stream.fromPure . fromIntegral . ord
356{-# INLINE charUtf8 #-}
357charUtf8 :: Monad m => Char -> Stream m Word8
358charUtf8 = Stream.unfold readCharUtf8
360-------------------------------------------------------------------------------
362-------------------------------------------------------------------------------
364-- | Stream a 'Word64' as eight bytes in the host byte order.
368{-# INLINE word64host #-}
369word64host :: Monad m => Word64 -> Stream m Word8
371#ifdef WORDS_BIGENDIAN
377-------------------------------------------------------------------------------
379-------------------------------------------------------------------------------
382 -- | Convert a Haskell type to a byte stream.
383 toBytes :: a -> Stream m Word8
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list