Add little-endian encoding functions for Word{16,32,64}. Add machine encoding functions for 64-bit signed int. These just convert it to an unsigned int and call the corresponding encoding function.

This commit is contained in:
Andrew Martin 2019-10-09 09:48:28 -04:00
parent e0b9d744cf
commit 3ad5261ff4
3 changed files with 92 additions and 3 deletions

View file

@ -4,6 +4,8 @@
* Introduce `consLensBE32` for efficient serialization of wire protocols * Introduce `consLensBE32` for efficient serialization of wire protocols
that require prefixing a payload with its length. that require prefixing a payload with its length.
* Add `int64BE` as a convenience.
* Add little-endian encoding functions for `Word16`, `Word32`, and `Word64`.
## 0.2.1.0 -- 2019-09-05 ## 0.2.1.0 -- 2019-09-05

View file

@ -54,10 +54,20 @@ module Data.ByteArray.Builder
, ascii , ascii
, char , char
-- ** Machine-Readable -- ** Machine-Readable
-- *** One
, word8
-- **** Big Endian
, word64BE , word64BE
, word32BE , word32BE
, word16BE , word16BE
, word8 , int64BE
-- **** Little Endian
, word64LE
, word32LE
, word16LE
, int64LE
-- *** Many
, word8Array
-- ** Prefixing with Length -- ** Prefixing with Length
, consLength32BE , consLength32BE
, consLength64BE , consLength64BE
@ -75,7 +85,7 @@ import Data.ByteString.Short.Internal (ShortByteString(SBS))
import Data.Bytes.Types (Bytes(Bytes),MutableBytes(MutableBytes)) import Data.Bytes.Types (Bytes(Bytes),MutableBytes(MutableBytes))
import Data.Char (ord) import Data.Char (ord)
import Data.Int (Int64,Int32,Int16,Int8) import Data.Int (Int64,Int32,Int16,Int8)
import Data.Primitive (ByteArray(..),MutableByteArray(..)) import Data.Primitive (ByteArray(..),MutableByteArray(..),PrimArray(..))
import Data.Primitive.ByteArray.Offset (MutableByteArrayOffset(..)) import Data.Primitive.ByteArray.Offset (MutableByteArrayOffset(..))
import Data.Text.Short (ShortText) import Data.Text.Short (ShortText)
import Data.Word (Word64,Word32,Word16,Word8) import Data.Word (Word64,Word32,Word16,Word8)
@ -218,6 +228,12 @@ bytes (Bytes src soff slen) = construct $ \(MutableBytes arr off len) -> if len
pure (Just (off + slen)) pure (Just (off + slen))
else pure Nothing else pure Nothing
-- | Create a builder from a slice of an array of 'Word8'. There is the same
-- as 'bytes' but is provided as a convenience for users working with different
-- types.
word8Array :: PrimArray Word8 -> Int -> Int -> Builder
word8Array (PrimArray arr) off len = bytes (Bytes (ByteArray arr) off len)
-- Internal function. Precondition, the referenced slice of the -- Internal function. Precondition, the referenced slice of the
-- byte sequence is UTF-8 encoded text. -- byte sequence is UTF-8 encoded text.
slicedUtf8TextJson :: ByteArray# -> Int# -> Int# -> Builder slicedUtf8TextJson :: ByteArray# -> Int# -> Int# -> Builder
@ -417,6 +433,31 @@ shrinkMutableByteArray :: MutableByteArray s -> Int -> ST s ()
shrinkMutableByteArray (MutableByteArray arr) (I# sz) = shrinkMutableByteArray (MutableByteArray arr) (I# sz) =
primitive_ (Exts.shrinkMutableByteArray# arr sz) primitive_ (Exts.shrinkMutableByteArray# arr sz)
-- | Requires exactly 8 bytes. Dump the octets of a 64-bit
-- signed integer in a little-endian fashion.
int64LE :: Int64 -> Builder
int64LE w = fromBounded Nat.constant (Bounded.int64LE w)
-- | Requires exactly 8 bytes. Dump the octets of a 64-bit
-- signed integer in a big-endian fashion.
int64BE :: Int64 -> Builder
int64BE w = fromBounded Nat.constant (Bounded.int64BE w)
-- | Requires exactly 8 bytes. Dump the octets of a 64-bit
-- word in a little-endian fashion.
word64LE :: Word64 -> Builder
word64LE w = fromBounded Nat.constant (Bounded.word64LE w)
-- | Requires exactly 4 bytes. Dump the octets of a 32-bit
-- word in a little-endian fashion.
word32LE :: Word32 -> Builder
word32LE w = fromBounded Nat.constant (Bounded.word32LE w)
-- | Requires exactly 2 bytes. Dump the octets of a 16-bit
-- word in a little-endian fashion.
word16LE :: Word16 -> Builder
word16LE w = fromBounded Nat.constant (Bounded.word16LE w)
-- | Requires exactly 8 bytes. Dump the octets of a 64-bit -- | Requires exactly 8 bytes. Dump the octets of a 64-bit
-- word in a big-endian fashion. -- word in a big-endian fashion.
word64BE :: Word64 -> Builder word64BE :: Word64 -> Builder

View file

@ -52,10 +52,18 @@ module Data.ByteArray.Builder.Bounded
, ascii , ascii
, char , char
-- ** Machine-Readable -- ** Machine-Readable
-- *** One
, word8
-- **** Big Endian
, word64BE , word64BE
, word32BE , word32BE
, word16BE , word16BE
, word8 , int64BE
-- **** Little Endian
, word64LE
, word32LE
, word16LE
, int64LE
-- * Encode Floating-Point Types -- * Encode Floating-Point Types
, doubleDec , doubleDec
) where ) where
@ -579,6 +587,26 @@ char c
byteFourFour :: Word -> Word byteFourFour :: Word -> Word
byteFourFour w = (0b00111111 .&. w) .|. 0b10000000 byteFourFour w = (0b00111111 .&. w) .|. 0b10000000
int64BE :: Int64 -> Builder 8
int64BE (I64# i) = word64BE (W64# (int2Word# i))
int64LE :: Int64 -> Builder 8
int64LE (I64# i) = word64LE (W64# (int2Word# i))
-- | Requires exactly 8 bytes. Dump the octets of a 64-bit
-- word in a little-endian fashion.
word64LE :: Word64 -> Builder 8
word64LE w = Unsafe.construct $ \arr off -> do
writeByteArray arr (off + 7) (fromIntegral @Word64 @Word8 (unsafeShiftR w 56))
writeByteArray arr (off + 6) (fromIntegral @Word64 @Word8 (unsafeShiftR w 48))
writeByteArray arr (off + 5) (fromIntegral @Word64 @Word8 (unsafeShiftR w 40))
writeByteArray arr (off + 4) (fromIntegral @Word64 @Word8 (unsafeShiftR w 32))
writeByteArray arr (off + 3) (fromIntegral @Word64 @Word8 (unsafeShiftR w 24))
writeByteArray arr (off + 2) (fromIntegral @Word64 @Word8 (unsafeShiftR w 16))
writeByteArray arr (off + 1) (fromIntegral @Word64 @Word8 (unsafeShiftR w 8))
writeByteArray arr (off ) (fromIntegral @Word64 @Word8 w)
pure (off + 8)
-- | Requires exactly 8 bytes. Dump the octets of a 64-bit -- | Requires exactly 8 bytes. Dump the octets of a 64-bit
-- word in a big-endian fashion. -- word in a big-endian fashion.
word64BE :: Word64 -> Builder 8 word64BE :: Word64 -> Builder 8
@ -593,6 +621,16 @@ word64BE w = Unsafe.construct $ \arr off -> do
writeByteArray arr (off + 7) (fromIntegral @Word64 @Word8 w) writeByteArray arr (off + 7) (fromIntegral @Word64 @Word8 w)
pure (off + 8) pure (off + 8)
-- | Requires exactly 4 bytes. Dump the octets of a 32-bit
-- word in a little-endian fashion.
word32LE :: Word32 -> Builder 4
word32LE w = Unsafe.construct $ \arr off -> do
writeByteArray arr (off + 3) (fromIntegral @Word32 @Word8 (unsafeShiftR w 24))
writeByteArray arr (off + 2) (fromIntegral @Word32 @Word8 (unsafeShiftR w 16))
writeByteArray arr (off + 1) (fromIntegral @Word32 @Word8 (unsafeShiftR w 8))
writeByteArray arr (off ) (fromIntegral @Word32 @Word8 w)
pure (off + 4)
-- | Requires exactly 4 bytes. Dump the octets of a 32-bit -- | Requires exactly 4 bytes. Dump the octets of a 32-bit
-- word in a big-endian fashion. -- word in a big-endian fashion.
word32BE :: Word32 -> Builder 4 word32BE :: Word32 -> Builder 4
@ -603,6 +641,14 @@ word32BE w = Unsafe.construct $ \arr off -> do
writeByteArray arr (off + 3) (fromIntegral @Word32 @Word8 w) writeByteArray arr (off + 3) (fromIntegral @Word32 @Word8 w)
pure (off + 4) pure (off + 4)
-- | Requires exactly 2 bytes. Dump the octets of a 16-bit
-- word in a little-endian fashion.
word16LE :: Word16 -> Builder 2
word16LE w = Unsafe.construct $ \arr off -> do
writeByteArray arr (off + 1) (fromIntegral @Word16 @Word8 (unsafeShiftR w 8))
writeByteArray arr (off ) (fromIntegral @Word16 @Word8 w)
pure (off + 2)
-- | Requires exactly 2 bytes. Dump the octets of a 16-bit -- | Requires exactly 2 bytes. Dump the octets of a 16-bit
-- word in a big-endian fashion. -- word in a big-endian fashion.
word16BE :: Word16 -> Builder 2 word16BE :: Word16 -> Builder 2