Handling simple blocks
Blocks are the basic components forming a frame. There exist three types of blocks:
- A raw block contains some data, without any compression, that must be copied while decoding.
- A RLE block is a block which contains a byte
b
and a lengthl
. Decoding it duplicates theb
bytel
times. - A compressed block contains much more complex information and is the basis of Zstandard compression capabilities.
For a start, you will implement the decoding of the first two block types.
Structure
✅ In a
block
module, add an enumeratedBlock
type with two variants (for now):RawBlock
which encapsulates a slice, andRLEBlock
which contains abyte
and arepeat
field.
✅ Implement
Block::parse()
which accepts a&mut ForwardByteParser
and returns a result containing a(Block, bool)
pair. Thebool
istrue
if the block is the last block of the frame.
Do not forget to add a dedicated Error
type in the block
module, as well as a Result
type alias. If the block type is invalid (3 is reserved), a Error::ReservedBlockType
should be returned. Also, you can call unimplemented!()
if you encounter a block of type 2 (compressed block) as we do not implement it yet.
✅ Implement the
Block::decode(self)
method which decodes a block (and destroys theBlock
object by takingself
).
Right now, decode()
does not need any other parameter. This will no longer be the case when we implement compressed blocks, as decoding a compressed block requires accessing a decoding context containing information about earlier operations. Also, decode()
needs to return a Result
: even if decoding cannot fail right now, it will later when more complex blocks are implemented.
✅ Add tests.
Here are two simple tests, you must add others, including for checking that errors are correctly detected:
use net7212::block::Block;
use net7212::parsing::ForwardByteParser;
#[test]
fn decode_raw_block_last() {
let mut parser = ForwardByteParser::new(&[
// Raw block, last block, len 4, content 0x10, 0x20, 0x30, 0x40,
// and an extra 0x50 at the end.
0x21, 0x0, 0x0, 0x10, 0x20, 0x30, 0x40, 0x50
]);
let (block, last) = Block::parse(&mut parser).unwrap();
assert!(last);
assert!(matches!(block, Block::RawBlock(&[0x10, 0x20, 0x30, 0x40])));
assert_eq!(1, parser.len());
let decoded = block.decode().unwrap();
assert_eq!(vec![0x10, 0x20, 0x30, 0x40], decoded);
}
#[test]
fn decode_rle_block_not_last() {
let mut parser = ForwardByteParser::new(&[
// RLE block, not last, byte 0x42 and repeat 0x30004,
// and an extra 0x50 at the end.
0x22, 0x0, 0x18, 0x42, 0x50
]);
let (block, last) = Block::parse(&mut parser).unwrap();
assert!(!last);
assert!(matches!(
block,
Block::RLEBlock {
byte: 0x42,
repeat: 196612
}
));
assert_eq!(1, parser.len());
let decoded = block.decode().unwrap();
assert_eq!(196612, decoded.len());
assert!(decoded.into_iter().all(|b| b == 0x42));
}