The decoding context
Within a Zstandard frame, blocks may rely on information provided by preceding blocks. For example, a block may reuse the same Huffman table as the previous block to decode literals. In this case, instead of describing the table again using FSE and recreating the decoder, an indication will be made to reuse the same decoder.
You will create a decoding_context
module to hold this state that can be shared between blocks, through a DecodingContext
. For now, the only things you will store in this DecodingContext
are:
- The frame window size which defines how far a sequence will be able to look back to output again some previously outputted data.
- The data that has been output already as a
Vec<u8>
, since sequences will be able to refer to this data. - The
HuffmanDecoder
used in previous blocks if any.
✅ Create a
DecodingContext
structure inside thedecoding_context
module with three fields so far, as shown below:
pub struct DecodingContext {
pub huffman: Option<HuffmanDecoder>,
pub decoded: Vec<u8>,
pub window_size: u64,
}
✅ Write a
DecodingContext::new()
constructor which receives a window size and checks it. If it is too large, an error (to be defined in the current module as usual) will be returned. Otherwise, a newDecodingContext
with no Huffman table and an empty decoded output will be used.
64MiB is enough and exceeds what is required by most encoders.
✅ Modify
Block::decode()
so that it takes aDecodingContext
as a mutable reference. Instead of returning the decoded data,Block::decode()
will add it to the current context'sdecoded
field, and returnOk(())
if everything went well.
✅ Modify
Frame::decode()
so that it creates a newDecodingContext
with the current frame size, and pass this context toBlock::decode()
. It will then return the content of the context'sdecoded
field if everything went well.
Don't forget to modify the tests as needed. Your program should still work as usual and pass the tests, even though it does nothing more than before, except check the window size.