The Get monad. A monad for efficiently building structures from
encoded lazy ByteStrings.
Primitives are available to decode words of various sizes, both big and
little endian.
Let's decode binary data representing illustrated here.
In this example the values are in little endian.
+------------------+--------------+-----------------+
| 32 bit timestamp | 32 bit price | 16 bit quantity |
+------------------+--------------+-----------------+
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.
MonadGetDefined in binary-0.8.9.3 · Data.Binary.Get.Internal
FunctorGetDefined in binary-0.8.9.3 · Data.Binary.Get.Internal
MonadFailGetDefined in binary-0.8.9.3 · Data.Binary.Get.Internal
ApplicativeGetDefined in binary-0.8.9.3 · Data.Binary.Get.Internal
AlternativeGetDefined in binary-0.8.9.3 · Data.Binary.Get.Internal
MonadPlusGetDefined in binary-0.8.9.3 · Data.Binary.Get.Internal
The lazy input interface
3 declarations
The lazy interface consumes a single lazy ByteString. It's the easiest
interface to get started with, but it doesn't support interleaving I/O and
parsing, unless lazy I/O is used.
There is no way to provide more input other than the initial data. To be
able to incrementally give more data, see the incremental input interface.
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.
The incremental interface gives you more control over how input is
provided during parsing. This lets you e.g. interleave parsing and
I/O.
The incremental interface consumes a strict ByteString at a time, each
being part of the total amount of input. If your decoder needs more input to
finish it will return a Partial with a continuation.
If there is no more input, provide it Nothing.
Fail will be returned if it runs into an error, together with a message,
the position and the remaining input.
If it succeeds it will return Done with the resulting value,
the position and the remaining input.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Deprecated. Use runGetIncremental instead. This function will be removed.
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. This will force all remaining input, don't use it.
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.