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
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

View file

@ -54,10 +54,20 @@ module Data.ByteArray.Builder
, ascii
, char
-- ** Machine-Readable
-- *** One
, word8
-- **** Big Endian
, word64BE
, word32BE
, word16BE
, word8
, int64BE
-- **** Little Endian
, word64LE
, word32LE
, word16LE
, int64LE
-- *** Many
, word8Array
-- ** Prefixing with Length
, consLength32BE
, consLength64BE
@ -75,7 +85,7 @@ import Data.ByteString.Short.Internal (ShortByteString(SBS))
import Data.Bytes.Types (Bytes(Bytes),MutableBytes(MutableBytes))
import Data.Char (ord)
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.Text.Short (ShortText)
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))
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
-- byte sequence is UTF-8 encoded text.
slicedUtf8TextJson :: ByteArray# -> Int# -> Int# -> Builder
@ -417,6 +433,31 @@ shrinkMutableByteArray :: MutableByteArray s -> Int -> ST s ()
shrinkMutableByteArray (MutableByteArray arr) (I# 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
-- word in a big-endian fashion.
word64BE :: Word64 -> Builder

View file

@ -52,10 +52,18 @@ module Data.ByteArray.Builder.Bounded
, ascii
, char
-- ** Machine-Readable
-- *** One
, word8
-- **** Big Endian
, word64BE
, word32BE
, word16BE
, word8
, int64BE
-- **** Little Endian
, word64LE
, word32LE
, word16LE
, int64LE
-- * Encode Floating-Point Types
, doubleDec
) where
@ -579,6 +587,26 @@ char c
byteFourFour :: Word -> Word
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
-- word in a big-endian fashion.
word64BE :: Word64 -> Builder 8
@ -593,6 +621,16 @@ word64BE w = Unsafe.construct $ \arr off -> do
writeByteArray arr (off + 7) (fromIntegral @Word64 @Word8 w)
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
-- word in a big-endian fashion.
word32BE :: Word32 -> Builder 4
@ -603,6 +641,14 @@ word32BE w = Unsafe.construct $ \arr off -> do
writeByteArray arr (off + 3) (fromIntegral @Word32 @Word8 w)
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
-- word in a big-endian fashion.
word16BE :: Word16 -> Builder 2