Add consLengthBE32
This commit is contained in:
parent
902eede957
commit
d52aecdc60
3 changed files with 36 additions and 1 deletions
|
@ -1,5 +1,10 @@
|
||||||
# Revision history for small-bytearray-builder
|
# Revision history for small-bytearray-builder
|
||||||
|
|
||||||
|
## 0.2.2.0 -- 2019-??-??
|
||||||
|
|
||||||
|
* Introduce `consLensBE32` for efficient serialization of wire protocols
|
||||||
|
that require prefixing a payload with its length.
|
||||||
|
|
||||||
## 0.2.1.0 -- 2019-09-05
|
## 0.2.1.0 -- 2019-09-05
|
||||||
|
|
||||||
* Stop exporting data constructor in `Data.ByteArray.Builder`.
|
* Stop exporting data constructor in `Data.ByteArray.Builder`.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
cabal-version: 2.2
|
cabal-version: 2.2
|
||||||
name: small-bytearray-builder
|
name: small-bytearray-builder
|
||||||
version: 0.2.1.0
|
version: 0.2.2.0
|
||||||
synopsis: Serialize to a small byte arrays
|
synopsis: Serialize to a small byte arrays
|
||||||
description:
|
description:
|
||||||
This is similar to the builder facilities provided by
|
This is similar to the builder facilities provided by
|
||||||
|
|
|
@ -58,6 +58,8 @@ module Data.ByteArray.Builder
|
||||||
, word32BE
|
, word32BE
|
||||||
, word16BE
|
, word16BE
|
||||||
, word8
|
, word8
|
||||||
|
-- ** Prefixing with Length
|
||||||
|
, consLength32BE
|
||||||
-- * Encode Floating-Point Types
|
-- * Encode Floating-Point Types
|
||||||
-- ** Human-Readable
|
-- ** Human-Readable
|
||||||
, doubleDec
|
, doubleDec
|
||||||
|
@ -77,6 +79,7 @@ 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)
|
||||||
import GHC.Exts (Int(I#),Char(C#),Int#,State#,ByteArray#,RealWorld,(>=#),(/=#))
|
import GHC.Exts (Int(I#),Char(C#),Int#,State#,ByteArray#,RealWorld,(>=#),(/=#))
|
||||||
|
import GHC.Exts ((+#),(-#))
|
||||||
import GHC.ST (ST(ST))
|
import GHC.ST (ST(ST))
|
||||||
|
|
||||||
import qualified Arithmetic.Nat as Nat
|
import qualified Arithmetic.Nat as Nat
|
||||||
|
@ -427,9 +430,36 @@ word32BE w = fromBounded Nat.constant (Bounded.word32BE w)
|
||||||
word16BE :: Word16 -> Builder
|
word16BE :: Word16 -> Builder
|
||||||
word16BE w = fromBounded Nat.constant (Bounded.word16BE w)
|
word16BE w = fromBounded Nat.constant (Bounded.word16BE w)
|
||||||
|
|
||||||
|
-- | Requires exactly 1 byte.
|
||||||
word8 :: Word8 -> Builder
|
word8 :: Word8 -> Builder
|
||||||
word8 w = fromBounded Nat.constant (Bounded.word8 w)
|
word8 w = fromBounded Nat.constant (Bounded.word8 w)
|
||||||
|
|
||||||
|
-- | Prefix a builder with its size in bytes. This size is
|
||||||
|
-- presented as a big-endian 32-bit word. The need to prefix
|
||||||
|
-- a builder with its length shows up a numbers of wire protocols
|
||||||
|
-- including those of PostgreSQL and Apache Kafka. Note the
|
||||||
|
-- equivalence:
|
||||||
|
--
|
||||||
|
-- > forall (n :: Int) (x :: Builder).
|
||||||
|
-- > let sz = sizeofByteArray (run n (consLength32BE x))
|
||||||
|
-- > consLength32BE x === word32BE (fromIntegral sz) <> x
|
||||||
|
--
|
||||||
|
-- However, using 'consLength32BE' is much more efficient here
|
||||||
|
-- since it only materializes the 'ByteArray' once.
|
||||||
|
consLength32BE :: Builder -> Builder
|
||||||
|
consLength32BE (Builder f) = Builder $ \arr off len s0 -> case len >=# 4# of
|
||||||
|
1# -> case f arr (off +# 4# ) (len -# 4# ) s0 of
|
||||||
|
(# s1, r #) -> case r of
|
||||||
|
(-1#) -> (# s1, (-1#) #)
|
||||||
|
_ ->
|
||||||
|
let ST g = UnsafeBounded.pasteST
|
||||||
|
(Bounded.word32BE (fromIntegral ((I# r - I# off) - 4)))
|
||||||
|
(MutableByteArray arr)
|
||||||
|
(I# off)
|
||||||
|
in case g s1 of
|
||||||
|
(# s2, _ #) -> (# s2, r #)
|
||||||
|
_ -> (# s0, (-1#) #)
|
||||||
|
|
||||||
-- ShortText is already UTF-8 encoded. This is a no-op.
|
-- ShortText is already UTF-8 encoded. This is a no-op.
|
||||||
shortTextToByteArray :: ShortText -> ByteArray
|
shortTextToByteArray :: ShortText -> ByteArray
|
||||||
shortTextToByteArray x = case TS.toShortByteString x of
|
shortTextToByteArray x = case TS.toShortByteString x of
|
||||||
|
|
Loading…
Reference in a new issue