proto3-wire-1.0.0: A low-level implementation of the Protocol Buffers (version 3) wire format

Safe HaskellNone
LanguageHaskell2010

Proto3.Wire.Builder

Contents

Description

This module extends the Data.ByteString.Builder module by memoizing the resulting length of each Builder

Example use:

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word32BE 42 <> charUtf8 'λ'))
[0,0,0,42,206,187]
Synopsis

Builder type

data Builder Source #

A Builder is like a Data.ByteString.Builder.Builder, but also memoizes the resulting length so that we can efficiently encode nested embedded messages.

You create a Builder by using one of the primitives provided in the "Create Builders" section.

You combine Builders using the Monoid and Semigroup instances.

You consume a Builder by using one of the utilities provided in the "Consume Builders" section.

Instances
Show Builder Source # 
Instance details

Defined in Proto3.Wire.Builder

Semigroup Builder Source # 
Instance details

Defined in Proto3.Wire.Builder

Monoid Builder Source # 
Instance details

Defined in Proto3.Wire.Builder

Create Builders

byteString :: ByteString -> Builder Source #

Convert a strict ByteString to a Builder

byteString (x <> y) = byteString x <> byteString y

byteString mempty = mempty
>>> byteString "ABC"
Proto3.Wire.Builder.lazyByteString "ABC"

lazyByteString :: ByteString -> Builder Source #

Convert a lazy ByteString to a Builder

Warning: evaluating the length will force the lazy ByteString's chunks, and they will remain allocated until you finish using the builder.

lazyByteString (x <> y) = lazyByteString x <> lazyByteString y

lazyByteString mempty = mempty
lazyByteString . toLazyByteString = id

toLazyByteString . lazyByteString = id
>>> lazyByteString "ABC"
Proto3.Wire.Builder.lazyByteString "ABC"

shortByteString :: ShortByteString -> Builder Source #

Convert a ShortByteString to a Builder

shortByteString (x <> y) = shortByteString x <> shortByteString y

shortByteString mempty = mempty
>>> shortByteString "ABC"
Proto3.Wire.Builder.lazyByteString "ABC"

word8 :: Word8 -> Builder Source #

Convert a Word8 to a Builder

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word8 42))
[42]

word16BE :: Word16 -> Builder Source #

Convert a Word16 to a Builder by storing the bytes in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word16BE 42))
[0,42]

word16LE :: Word16 -> Builder Source #

Convert a Word16 to a Builder by storing the bytes in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word16LE 42))
[42,0]

word32BE :: Word32 -> Builder Source #

Convert a Word32 to a Builder by storing the bytes in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word32BE 42))
[0,0,0,42]

word32LE :: Word32 -> Builder Source #

Convert a Word32 to a Builder by storing the bytes in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word32LE 42))
[42,0,0,0]

word64BE :: Word64 -> Builder Source #

Convert a Word64 to a Builder by storing the bytes in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word64BE 42))
[0,0,0,0,0,0,0,42]

word64LE :: Word64 -> Builder Source #

Convert a Word64 to a Builder by storing the bytes in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (word64LE 42))
[42,0,0,0,0,0,0,0]

word64Base128LEVar :: Word64 -> Builder Source #

Convert a Word64 to a Builder using this variable-length encoding:

  1. Convert the given value to a base 128 representation without unnecessary digits (that is, omit zero digits unless they are less significant than nonzero digits).
  2. Present those base-128 digits in order of increasing significance (that is, in little-endian order).
  3. Add 128 to every digit except the most significant digit, yielding a sequence of octets terminated by one that is <= 127.

This encoding is used in the wire format of Protocol Buffers version 3.

int8 :: Int8 -> Builder Source #

Convert a Int8 to a Builder

>>> Data.ByteString.Lazy.unpack (toLazyByteString (int8 (-5)))
[251]

int16BE :: Int16 -> Builder Source #

Convert an Int16 to a Builder by storing the bytes in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (int16BE (-5)))
[255,251]

int16LE :: Int16 -> Builder Source #

Convert an Int16 to a Builder by storing the bytes in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (int16LE (-5)))
[251,255]

int32BE :: Int32 -> Builder Source #

Convert an Int32 to a Builder by storing the bytes in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (int32BE (-5)))
[255,255,255,251]

int32LE :: Int32 -> Builder Source #

Convert an Int32 to a Builder by storing the bytes in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (int32LE (-5)))
[251,255,255,255]

int64BE :: Int64 -> Builder Source #

Convert an Int64 to a Builder by storing the bytes in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (int64BE (-5)))
[255,255,255,255,255,255,255,251]

int64LE :: Int64 -> Builder Source #

Convert an Int64 to a Builder by storing the bytes in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (int64LE (-5)))
[251,255,255,255,255,255,255,255]

floatBE :: Float -> Builder Source #

Convert a Float to a Builder by storing the bytes in IEEE-754 format in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (floatBE 4.2))
[64,134,102,102]

floatLE :: Float -> Builder Source #

Convert a Float to a Builder by storing the bytes in IEEE-754 format in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (floatLE 4.2))
[102,102,134,64]

doubleBE :: Double -> Builder Source #

Convert a Double to a Builder by storing the bytes in IEEE-754 format in big-endian order

In other words, the most significant byte is stored first and the least significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (doubleBE 4.2))
[64,16,204,204,204,204,204,205]

doubleLE :: Double -> Builder Source #

Convert a Double to a Builder by storing the bytes in IEEE-754 format in little-endian order

In other words, the least significant byte is stored first and the most significant byte is stored last

>>> Data.ByteString.Lazy.unpack (toLazyByteString (doubleLE 4.2))
[205,204,204,204,204,204,16,64]

char7 :: Char -> Builder Source #

Convert an ASCII Char to a Builder

Careful: If you provide a Unicode character that is not part of the ASCII alphabet this will only encode the lowest 7 bits

>>> char7 ';'
Proto3.Wire.Builder.lazyByteString ";"
>>> char7 'λ' -- Example of truncation
Proto3.Wire.Builder.lazyByteString ";"

string7 :: String -> Builder Source #

Convert an ASCII String to a Builder

Careful: If you provide a Unicode String that has non-ASCII characters then this will only encode the lowest 7 bits of each character

string7 (x <> y) = string7 x <> string7 y

string7 mempty = mempty
>>> string7 "ABC"
Proto3.Wire.Builder.lazyByteString "ABC"
>>> string7 "←↑→↓" -- Example of truncation
Proto3.Wire.Builder.lazyByteString "\DLE\DC1\DC2\DC3"

char8 :: Char -> Builder Source #

Convert an ISO/IEC 8859-1 Char to a Builder

Careful: If you provide a Unicode character that is not part of the ISO/IEC 8859-1 alphabet then this will only encode the lowest 8 bits

>>> char8 ';'
Proto3.Wire.Builder.lazyByteString ";"
>>> char8 'λ' -- Example of truncation
Proto3.Wire.Builder.lazyByteString "\187"

string8 :: String -> Builder Source #

Convert an ISO/IEC 8859-1 String to a Builder

Careful: If you provide a Unicode String that has non-ISO/IEC 8859-1 characters then this will only encode the lowest 8 bits of each character

string8 (x <> y) = string8 x <> string8 y

string8 mempty = mempty
>>> string8 "ABC"
Proto3.Wire.Builder.lazyByteString "ABC"
>>> string8 "←↑→↓" -- Example of truncation
Proto3.Wire.Builder.lazyByteString "\144\145\146\147"

charUtf8 :: Char -> Builder Source #

Convert a Unicode Char to a Builder using a UTF-8 encoding

>>> charUtf8 'A'
Proto3.Wire.Builder.lazyByteString "A"
>>> charUtf8 'λ'
Proto3.Wire.Builder.lazyByteString "\206\187"
>>> hPutBuilder System.IO.stdout (charUtf8 'λ' <> charUtf8 '\n')
λ

stringUtf8 :: String -> Builder Source #

Convert a Unicode String to a Builder using a UTF-8 encoding

stringUtf8 (x <> y) = stringUtf8 x <> stringUtf8 y

stringUtf8 mempty = mempty
>>> stringUtf8 "ABC"
Proto3.Wire.Builder.lazyByteString "ABC"
>>> stringUtf8 "←↑→↓"
Proto3.Wire.Builder.lazyByteString "\226\134\144\226\134\145\226\134\146\226\134\147"
>>> hPutBuilder System.IO.stdout (stringUtf8 "←↑→↓\n")
←↑→↓

Consume Builders

builderLength :: Builder -> Word Source #

Retrieve the length of a Builder

builderLength (x <> y) = builderLength x + builderLength y

builderLength mempty = 0
>>> builderLength (word32BE 42)
4
>>> builderLength (stringUtf8 "ABC")
3

rawBuilder :: Builder -> Builder Source #

Retrieve the underlying Data.ByteString.Builder.Builder

rawBuilder (x <> y) = rawBuilder x <> rawBuilder y

rawBuilder mempty = mempty
>>> Data.ByteString.Builder.toLazyByteString (rawBuilder (stringUtf8 "ABC"))
"ABC"

toLazyByteString :: Builder -> ByteString Source #

Create a lazy ByteString from a Builder

toLazyByteString (x <> y) = toLazyByteString x <> toLazyByteString y

toLazyByteString mempty = mempty
>>> toLazyByteString (stringUtf8 "ABC")
"ABC"

hPutBuilder :: Handle -> Builder -> IO () Source #

Write a Builder to a Handle

hPutBuilder handle (x <> y) = hPutBuilder handle x <> hPutBuilder handle y

hPutBuilder handle mempty = mempty
>>> hPutBuilder System.IO.stdout (stringUtf8 "ABC\n")
ABC

Internal API

unsafeMakeBuilder :: Word -> Builder -> Builder Source #

Create a Builder from a Data.ByteString.Builder.Builder and a length. This is unsafe because you are responsible for ensuring that the provided length value matches the length of the Data.ByteString.Builder.Builder

>>> unsafeMakeBuilder 3 (Data.ByteString.Builder.stringUtf8 "ABC")
Proto3.Wire.Builder.lazyByteString "ABC"