-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Binary serialisation for Haskell values using lazy ByteStrings -- -- Efficient, pure binary serialisation using lazy ByteStrings. Haskell -- values may be encoded to and from binary formats, written to disk as -- binary, or sent over the network. The format used can be automatically -- generated, or you can choose to implement a custom format if needed. -- Serialisation speeds of over 1 G/sec have been observed, so this -- library should be suitable for high performance scenarios. @package binary @version 0.8.9.3 -- | Efficient constructions of lazy bytestrings. -- -- This now re-exports Builder. module Data.Binary.Builder -- | Builders denote sequences of bytes. They are Monoids -- where mempty is the zero-length sequence and mappend is -- concatenation, which runs in O(1). data Builder -- | Execute a Builder and return the generated chunks as a -- LazyByteString. The work is performed lazy, i.e., only when a -- chunk of the LazyByteString is forced. toLazyByteString :: Builder -> LazyByteString -- | O(1). The empty Builder, satisfying -- --
toLazyByteString empty = -- empty
toLazyByteString (singleton b) = -- singleton b
toLazyByteString (append x y) = append -- (toLazyByteString x) (toLazyByteString y)
toLazyByteString (fromByteString bs) = -- fromChunks [bs]
toLazyByteString (fromLazyByteString bs) = -- bs
-- +------------------+--------------+-----------------+ -- | 32 bit timestamp | 32 bit price | 16 bit quantity | -- +------------------+--------------+-----------------+ ---- -- A corresponding Haskell value looks like this: -- --
-- data Trade = Trade
-- { timestamp :: !Word32
-- , price :: !Word32
-- , qty :: !Word16
-- } deriving (Show)
--
--
--
-- The fields in Trade are marked as strict (using !)
-- since we don't need laziness here. In practise, you would probably
-- consider using the UNPACK pragma as well.
-- https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/pragmas.html#unpack-pragma
--
-- Now, let's have a look at a decoder for this format.
--
-- -- getTrade :: Get Trade -- getTrade = do -- timestamp <- getWord32le -- price <- getWord32le -- quantity <- getWord16le -- return $! Trade timestamp price quantity -- ---- -- Or even simpler using applicative style: -- --
-- getTrade' :: Get Trade -- getTrade' = Trade <$> getWord32le <*> getWord32le <*> getWord16le -- ---- -- There are two kinds of ways to execute this decoder, the lazy input -- method and the incremental input method. Here we will use the lazy -- input method. -- -- Let's first define a function that decodes many Trades. -- --
-- getTrades :: Get [Trade] -- getTrades = do -- empty <- isEmpty -- if empty -- then return [] -- else do trade <- getTrade -- trades <- getTrades -- return (trade:trades) -- ---- -- Finally, we run the decoder: -- --
-- lazyIOExample :: IO [Trade] -- lazyIOExample = do -- input <- BL.readFile "trades.bin" -- return (runGet getTrades input) -- ---- -- This decoder has the downside that it will need to read all the input -- before it can return. On the other hand, it will not return anything -- until it knows it could decode without any decoder errors. -- -- You could also refactor to a left-fold, to decode in a more streaming -- fashion, and get the following decoder. It will start to return data -- without knowing that it can decode all input. -- --
-- incrementalExample :: BL.ByteString -> [Trade] -- incrementalExample input0 = go decoder input0 -- where -- decoder = runGetIncremental getTrade -- go :: Decoder Trade -> BL.ByteString -> [Trade] -- go (Done leftover _consumed trade) input = -- trade : go decoder (BL.chunk leftover input) -- go (Partial k) input = -- go (k . takeHeadChunk $ input) (dropHeadChunk input) -- go (Fail _leftover _consumed msg) _input = -- error msg -- -- takeHeadChunk :: BL.ByteString -> Maybe BS.ByteString -- takeHeadChunk lbs = -- case lbs of -- (BL.Chunk bs _) -> Just bs -- _ -> Nothing -- -- dropHeadChunk :: BL.ByteString -> BL.ByteString -- dropHeadChunk lbs = -- case lbs of -- (BL.Chunk _ lbs') -> lbs' -- _ -> BL.Empty -- ---- -- The lazyIOExample uses lazy I/O to read the file from the -- disk, which is not suitable in all applications, and certainly not if -- you need to read from a socket which has higher likelihood to fail. To -- address these needs, use the incremental input method like in -- incrementalExample. For an example of how to read -- incrementally from a Handle, see the implementation of -- decodeFileOrFail. module Data.Binary.Get data Get a -- | The simplest interface to run a Get decoder. If the decoder -- runs into an error, calls fail, or runs out of input, it will -- call error. runGet :: Get a -> ByteString -> a -- | Run a Get monad and return Left on failure and -- Right on success. In both cases any unconsumed input and the -- number of bytes consumed is returned. In the case of failure, a -- human-readable error message is included as well. runGetOrFail :: Get a -> ByteString -> Either (ByteString, ByteOffset, String) (ByteString, ByteOffset, a) -- | An offset, counted in bytes. type ByteOffset = Int64 -- | A decoder procuced by running a Get monad. data Decoder a -- | The decoder ran into an error. The decoder either used fail or -- was not provided enough input. Contains any unconsumed input and the -- number of bytes consumed. Fail :: !ByteString -> {-# UNPACK #-} !ByteOffset -> String -> Decoder a -- | The decoder has consumed the available input and needs more to -- continue. Provide Just if more input is available and -- Nothing otherwise, and you will get a new Decoder. Partial :: (Maybe ByteString -> Decoder a) -> Decoder a -- | The decoder has successfully finished. Except for the output value you -- also get any unused input as well as the number of bytes consumed. Done :: !ByteString -> {-# UNPACK #-} !ByteOffset -> a -> Decoder a -- | Run a Get monad. See Decoder for what to do next, like -- providing input, handling decoder errors and to get the output value. -- Hint: Use the helper functions pushChunk, pushChunks and -- pushEndOfInput. runGetIncremental :: Get a -> Decoder a -- | Feed a Decoder with more input. If the Decoder is -- Done or Fail it will add the input to ByteString -- of unconsumed input. -- --
-- runGetIncremental myParser `pushChunk` myInput1 `pushChunk` myInput2 --pushChunk :: Decoder a -> ByteString -> Decoder a -- | Feed a Decoder with more input. If the Decoder is -- Done or Fail it will add the input to ByteString -- of unconsumed input. -- --
-- runGetIncremental myParser `pushChunks` myLazyByteString --pushChunks :: Decoder a -> ByteString -> Decoder a -- | Tell a Decoder that there is no more input. This passes -- Nothing to a Partial decoder, otherwise returns the -- decoder unchanged. pushEndOfInput :: Decoder a -> Decoder a -- | Skip ahead n bytes. Fails if fewer than n bytes are -- available. skip :: Int -> Get () -- | Test whether all input has been consumed, i.e. there are no remaining -- undecoded bytes. isEmpty :: Get Bool -- | Get the total number of bytes read to this point. bytesRead :: Get Int64 -- | Isolate a decoder to operate with a fixed number of bytes, and fail if -- fewer bytes were consumed, or more bytes were attempted to be -- consumed. If the given decoder fails, isolate will also fail. -- Offset from bytesRead will be relative to the start of -- isolate, not the absolute of the input. isolate :: Int -> Get a -> Get a -- | Run the given decoder, but without consuming its input. If the given -- decoder fails, then so will this function. lookAhead :: Get a -> Get a -- | Run the given decoder, and only consume its input if it returns -- Just. If Nothing is returned, the input will be -- unconsumed. If the given decoder fails, then so will this function. lookAheadM :: Get (Maybe a) -> Get (Maybe a) -- | Run the given decoder, and only consume its input if it returns -- Right. If Left is returned, the input will be -- unconsumed. If the given decoder fails, then so will this function. lookAheadE :: Get (Either a b) -> Get (Either a b) -- | Label a decoder. If the decoder fails, the label will be appended on a -- new line to the error message string. label :: String -> Get a -> Get a -- | An efficient get method for strict ByteStrings. Fails if fewer than -- n bytes are left in the input. If n <= 0 then the -- empty string is returned. getByteString :: Int -> Get ByteString -- | An efficient get method for lazy ByteStrings. Fails if fewer than -- n bytes are left in the input. getLazyByteString :: Int64 -> Get ByteString -- | Get a lazy ByteString that is terminated with a NUL byte. The returned -- string does not contain the NUL byte. Fails if it reaches the end of -- input without finding a NUL. getLazyByteStringNul :: Get ByteString -- | Get the remaining bytes as a lazy ByteString. Note that this can be an -- expensive function to use as it forces reading all input and keeping -- the string in-memory. getRemainingLazyByteString :: Get ByteString -- | Read a Word8 from the monad state getWord8 :: Get Word8 -- | Read a Word16 in big endian format getWord16be :: Get Word16 -- | Read a Word32 in big endian format getWord32be :: Get Word32 -- | Read a Word64 in big endian format getWord64be :: Get Word64 -- | Read a Word16 in little endian format getWord16le :: Get Word16 -- | Read a Word32 in little endian format getWord32le :: Get Word32 -- | Read a Word64 in little endian format getWord64le :: Get Word64 -- | O(1). Read a single native machine word. The word is read in -- host order, host endian form, for the machine you're on. On a 64 bit -- machine the Word is an 8 byte value, on a 32 bit machine, 4 bytes. getWordhost :: Get Word -- | O(1). Read a 2 byte Word16 in native host order and host -- endianness. getWord16host :: Get Word16 -- | O(1). Read a Word32 in native host order and host endianness. getWord32host :: Get Word32 -- | O(1). Read a Word64 in native host order and host endianess. getWord64host :: Get Word64 -- | Read an Int8 from the monad state getInt8 :: Get Int8 -- | Read an Int16 in big endian format. getInt16be :: Get Int16 -- | Read an Int32 in big endian format. getInt32be :: Get Int32 -- | Read an Int64 in big endian format. getInt64be :: Get Int64 -- | Read an Int16 in little endian format. getInt16le :: Get Int16 -- | Read an Int32 in little endian format. getInt32le :: Get Int32 -- | Read an Int64 in little endian format. getInt64le :: Get Int64 -- | O(1). Read a single native machine word in native host order. -- It works in the same way as getWordhost. getInthost :: Get Int -- | O(1). Read a 2 byte Int16 in native host order and host -- endianness. getInt16host :: Get Int16 -- | O(1). Read an Int32 in native host order and host endianness. getInt32host :: Get Int32 -- | O(1). Read an Int64 in native host order and host endianess. getInt64host :: Get Int64 -- | Read a Float in big endian IEEE-754 format. getFloatbe :: Get Float -- | Read a Float in little endian IEEE-754 format. getFloatle :: Get Float -- | Read a Float in IEEE-754 format and host endian. getFloathost :: Get Float -- | Read a Double in big endian IEEE-754 format. getDoublebe :: Get Double -- | Read a Double in little endian IEEE-754 format. getDoublele :: Get Double -- | Read a Double in IEEE-754 format and host endian. getDoublehost :: Get Double -- | DEPRECATED. Provides compatibility with previous versions of this -- library. Run a Get monad and return a tuple with three values. -- The first value is the result of the decoder. The second and third are -- the unused input, and the number of consumed bytes. -- | Deprecated: Use runGetIncremental instead. This function will be -- removed. runGetState :: Get a -> ByteString -> ByteOffset -> (a, ByteString, ByteOffset) -- | DEPRECATED. Get the number of bytes of remaining input. Note that this -- is an expensive function to use as in order to calculate how much -- input remains, all input has to be read and kept in-memory. The -- decoder keeps the input as a strict bytestring, so you are likely -- better off by calculating the remaining input in another way. -- | Deprecated: This will force all remaining input, don't use it. remaining :: Get Int64 -- | DEPRECATED. Same as getByteString. -- | Deprecated: Use getByteString instead of -- getBytes. getBytes :: Int -> Get ByteString -- | The Put monad. A monad for efficiently constructing lazy bytestrings. module Data.Binary.Put -- | Put merely lifts Builder into a Writer monad, applied to (). type Put = PutM () -- | The PutM type. A Writer monad over the efficient Builder monoid. newtype PutM a Put :: PairS a -> PutM a [unPut] :: PutM a -> PairS a -- | Run the Put monad with a serialiser runPut :: Put -> ByteString -- | Run the Put monad with a serialiser and get its result runPutM :: PutM a -> (a, ByteString) putBuilder :: Builder -> Put -- | Run the Put monad execPut :: PutM a -> Builder -- | Pop the ByteString we have constructed so far, if any, yielding a new -- chunk in the result ByteString. flush :: Put -- | Efficiently write a byte into the output buffer putWord8 :: Word8 -> Put -- | Efficiently write a signed byte into the output buffer putInt8 :: Int8 -> Put -- | An efficient primitive to write a strict ByteString into the output -- buffer. It flushes the current buffer, and writes the argument into a -- new chunk. putByteString :: ByteString -> Put -- | Write a lazy ByteString efficiently, simply appending the lazy -- ByteString chunks to the output buffer putLazyByteString :: ByteString -> Put -- | Write ShortByteString to the buffer putShortByteString :: ShortByteString -> Put -- | Write a Word16 in big endian format putWord16be :: Word16 -> Put -- | Write a Word32 in big endian format putWord32be :: Word32 -> Put -- | Write a Word64 in big endian format putWord64be :: Word64 -> Put -- | Write an Int16 in big endian format putInt16be :: Int16 -> Put -- | Write an Int32 in big endian format putInt32be :: Int32 -> Put -- | Write an Int64 in big endian format putInt64be :: Int64 -> Put -- | Write a Float in big endian IEEE-754 format. putFloatbe :: Float -> Put -- | Write a Double in big endian IEEE-754 format. putDoublebe :: Double -> Put -- | Write a Word16 in little endian format putWord16le :: Word16 -> Put -- | Write a Word32 in little endian format putWord32le :: Word32 -> Put -- | Write a Word64 in little endian format putWord64le :: Word64 -> Put -- | Write an Int16 in little endian format putInt16le :: Int16 -> Put -- | Write an Int32 in little endian format putInt32le :: Int32 -> Put -- | Write an Int64 in little endian format putInt64le :: Int64 -> Put -- | Write a Float in little endian IEEE-754 format. putFloatle :: Float -> Put -- | Write a Double in little endian IEEE-754 format. putDoublele :: Double -> Put -- | O(1). Write a single native machine word. The word is written -- in host order, host endian form, for the machine you're on. On a 64 -- bit machine the Word is an 8 byte value, on a 32 bit machine, 4 bytes. -- Values written this way are not portable to different endian or word -- sized machines, without conversion. putWordhost :: Word -> Put -- | O(1). Write a Word16 in native host order and host endianness. -- For portability issues see putWordhost. putWord16host :: Word16 -> Put -- | O(1). Write a Word32 in native host order and host endianness. -- For portability issues see putWordhost. putWord32host :: Word32 -> Put -- | O(1). Write a Word64 in native host order On a 32 bit machine -- we write two host order Word32s, in big endian form. For portability -- issues see putWordhost. putWord64host :: Word64 -> Put -- | O(1). Write a single native machine word. The word is written -- in host order, host endian form, for the machine you're on. On a 64 -- bit machine the Int is an 8 byte value, on a 32 bit machine, 4 bytes. -- Values written this way are not portable to different endian or word -- sized machines, without conversion. putInthost :: Int -> Put -- | O(1). Write an Int16 in native host order and host endianness. -- For portability issues see putInthost. putInt16host :: Int16 -> Put -- | O(1). Write an Int32 in native host order and host endianness. -- For portability issues see putInthost. putInt32host :: Int32 -> Put -- | O(1). Write an Int64 in native host order On a 32 bit machine -- we write two host order Int32s, in big endian form. For portability -- issues see putInthost. putInt64host :: Int64 -> Put -- | Write a Float in native in IEEE-754 format and host endian. putFloathost :: Float -> Put -- | Write a Double in native in IEEE-754 format and host endian. putDoublehost :: Double -> Put -- | Write a character using UTF-8 encoding. putCharUtf8 :: Char -> Put -- | Write a String using UTF-8 encoding. putStringUtf8 :: String -> Put instance GHC.Internal.Base.Applicative Data.Binary.Put.PutM instance GHC.Internal.Base.Functor Data.Binary.Put.PutM instance GHC.Internal.Base.Monad Data.Binary.Put.PutM instance GHC.Internal.Base.Monoid (Data.Binary.Put.PutM ()) instance GHC.Internal.Base.Semigroup (Data.Binary.Put.PutM ()) -- | Binary serialisation of Haskell values to and from lazy -- ByteStrings. The Binary library provides methods for encoding -- Haskell values as streams of bytes directly in memory. The resulting -- ByteString can then be written to disk, sent over the network, -- or further processed (for example, compressed with gzip). -- -- The binary package is notable in that it provides both pure, -- and high performance serialisation. -- -- Values encoded using the Binary class are always encoded in -- network order (big endian) form, and encoded data should be portable -- across machine endianness, word size, or compiler version. For -- example, data encoded using the Binary class could be written -- on any machine, and read back on any another. -- -- If the specifics of the data format is not important to you, for -- example, you are more interested in serializing and deserializing -- values than in which format will be used, it is possible to derive -- Binary instances using the generic support. See -- GBinaryGet and GBinaryPut. -- -- If you have specific requirements about the encoding format, you can -- use the encoding and decoding primitives directly, see the modules -- Data.Binary.Get and Data.Binary.Put. module Data.Binary -- | The Binary class provides put and get, methods to -- encode and decode a Haskell value to a lazy ByteString. It -- mirrors the Read and Show classes for textual -- representation of Haskell types, and is suitable for serialising -- Haskell values to disk, over the network. -- -- For decoding and generating simple external binary formats (e.g. C -- structures), Binary may be used, but in general is not suitable for -- complex protocols. Instead use the Put and Get -- primitives directly. -- -- Instances of Binary should satisfy the following property: -- --
-- decode . encode == id ---- -- That is, the get and put methods should be the inverse -- of each other. A range of instances are provided for basic Haskell -- types. class Binary t -- | Encode a value in the Put monad. put :: Binary t => t -> Put ($dmput) :: (Binary t, Generic t, GBinaryPut (Rep t)) => t -> Put -- | Decode a value in the Get monad get :: Binary t => Get t ($dmget) :: (Binary t, Generic t, GBinaryGet (Rep t)) => Get t -- | Encode a list of values in the Put monad. The default implementation -- may be overridden to be more efficient but must still have the same -- encoding format. putList :: Binary t => [t] -> Put class GBinaryGet (f :: k -> Type) gget :: forall (t :: k). GBinaryGet f => Get (f t) class GBinaryPut (f :: k -> Type) gput :: forall (t :: k). GBinaryPut f => f t -> Put data Get a -- | Put merely lifts Builder into a Writer monad, applied to (). type Put = PutM () -- | Efficiently write a byte into the output buffer putWord8 :: Word8 -> Put -- | Read a Word8 from the monad state getWord8 :: Get Word8 -- | Encode a value using binary serialisation to a lazy ByteString. encode :: Binary a => a -> ByteString -- | Decode a value from a lazy ByteString, reconstructing the original -- structure. decode :: Binary a => ByteString -> a -- | Decode a value from a lazy ByteString. Returning Left on -- failure and Right on success. In both cases the unconsumed -- input and the number of consumed bytes is returned. In case of -- failure, a human-readable error message will be returned as well. decodeOrFail :: Binary a => ByteString -> Either (ByteString, ByteOffset, String) (ByteString, ByteOffset, a) -- | Lazily serialise a value to a file. -- -- This is just a convenience function, it's defined simply as: -- --
-- encodeFile f = B.writeFile f . encode ---- -- So for example if you wanted to compress as well, you could use: -- --
-- B.writeFile f . compress . encode --encodeFile :: Binary a => FilePath -> a -> IO () -- | Decode a value from a file. In case of errors, error will be -- called with the error message. decodeFile :: Binary a => FilePath -> IO a -- | Decode a value from a file. In case of success, the value will be -- returned in Right. In case of decoder errors, the error message -- together with the byte offset will be returned. decodeFileOrFail :: Binary a => FilePath -> IO (Either (ByteOffset, String) a)