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
band a lengthl. Decoding it duplicates thebbyteltimes. - 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
blockmodule, add an enumeratedBlocktype with two variants (for now):RawBlockwhich encapsulates a slice, andRLEBlockwhich contains abyteand arepeatfield.
✅ Implement
Block::parse()which accepts a&mut ForwardByteParserand returns a result containing a(Block, bool)pair. Theboolistrueif 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 theBlockobject 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));
}