diff --git a/crates/flat/src/decode/decoder.rs b/crates/flat/src/decode/decoder.rs index d58e800f..972e2332 100644 --- a/crates/flat/src/decode/decoder.rs +++ b/crates/flat/src/decode/decoder.rs @@ -18,7 +18,7 @@ impl<'b> Decoder<'b> { } } - /// Encode any type that implements [`Decode`]. + /// Decode any type that implements [`Decode`]. pub fn decode>(&mut self) -> Result { T::decode(self) } @@ -35,9 +35,10 @@ impl<'b> Decoder<'b> { Ok(zigzag::to_isize(self.word()?)) } - /// Decode a single bit of the buffer to get a bool - /// We mask out a single bit of the buffer based on used bits - /// and check if it is 0 for false or 1 for true + /// Decode a single bit of the buffer to get a bool. + /// We mask out a single bit of the buffer based on used bits. + /// and check if it is 0 for false or 1 for true. + // TODO: use bit() instead of this custom implementation. pub fn bool(&mut self) -> Result { let current_byte = self.buffer[self.pos]; let b = 0 != (current_byte & (128 >> self.used_bits)); @@ -99,16 +100,26 @@ impl<'b> Decoder<'b> { String::from_utf8(Vec::::decode(self)?).map_err(Error::from) } + /// Decodes a filler of max one byte size. + /// Decodes bits until we hit a bit that is 1. + /// Expects that the 1 is at the end of the current byte in the buffer. pub fn filler(&mut self) -> Result<(), Error> { while self.zero()? {} Ok(()) } + /// Decode a word of any size. + /// This is byte alignment agnostic. + /// First we decode the next 8 bits of the buffer. + /// We take the 7 least significant bits as the 7 least significant bits of the current unsigned integer. + /// If the most significant bit of the 8 bits is 1 then we take the next 8 and repeat the process above, + /// filling in the next 7 least significant bits of the unsigned integer and so on. + /// If the most significant bit was instead 0 we stop decoding any more bits. pub fn word(&mut self) -> Result { let mut leading_bit = 1; let mut final_word: usize = 0; let mut shl: usize = 0; - // continue looping if lead bit is 1 otherwise exit + // continue looping if lead bit is 1 which is 128 as a u8 otherwise exit while leading_bit > 0 { let word8 = self.bits8(8)?; let word7 = word8 & 127; @@ -119,6 +130,13 @@ impl<'b> Decoder<'b> { Ok(final_word) } + /// Decode a list of items with a decoder function. + /// This is byte alignment agnostic. + /// Decode a bit from the buffer. + /// If 0 then stop. + /// Otherwise we decode an item in the list with the decoder function passed in. + /// Then decode the next bit in the buffer and repeat above. + /// Returns a list of items decoded with the decoder function. pub fn decode_list_with>( &mut self, decoder_func: for<'r> fn(&'r mut Decoder) -> Result, @@ -130,12 +148,20 @@ impl<'b> Decoder<'b> { Ok(vec_array) } + /// Decode the next bit in the buffer. + /// If the bit was 0 then return true. + /// Otherwise return false. + /// Throws EndOfBuffer error if used at the end of the array. fn zero(&mut self) -> Result { let current_bit = self.bit()?; Ok(!current_bit) } + /// Decode the next bit in the buffer. + /// If the bit was 1 then return true. + /// Otherwise return false. + /// Throws EndOfBuffer error if used at the end of the array. fn bit(&mut self) -> Result { if self.pos >= self.buffer.len() { return Err(Error::EndOfBuffer); @@ -148,6 +174,13 @@ impl<'b> Decoder<'b> { Ok(b) } + /// Decode a byte array. + /// Throws a BufferNotByteAligned error if the buffer is not byte aligned + /// Decodes the next byte to get the array length up to a max of 255. + /// We decode bytes equal to the array length to form the byte array. + /// If the following byte for array length is not 0 we decode it and repeat above to continue decoding the byte array. + /// We stop once we hit a byte array length of 0. + /// If array length is 0 for first byte array length the we return a empty array. fn byte_array(&mut self) -> Result, Error> { if self.used_bits != 0 { return Err(Error::BufferNotByteAligned); @@ -178,7 +211,14 @@ impl<'b> Decoder<'b> { Ok(blk_array) } - // can decode up to a max of 8 bits + /// Decode up to 8 bits. + /// This is byte alignment agnostic. + /// If num_bits is greater than the 8 we throw an IncorrectNumBits error. + /// First we decode the next num_bits of bits in the buffer. + /// If there are less unused bits in the current byte in the buffer than num_bits, + /// then we decode the remaining bits from the most significant bits in the next byte in the buffer. + /// Otherwise we decode the unused bits from the current byte. + /// Returns the decoded value up to a byte in size. pub fn bits8(&mut self, num_bits: usize) -> Result { if num_bits > 8 { return Err(Error::IncorrectNumBits); @@ -201,6 +241,8 @@ impl<'b> Decoder<'b> { Ok(x) } + /// Ensures the buffer has the required bytes passed in by required_bytes. + /// Throws a NotEnoughBytes error if there are less bytes remaining in the buffer than required_bytes. fn ensure_bytes(&mut self, required_bytes: usize) -> Result<(), Error> { if required_bytes as isize > self.buffer.len() as isize - self.pos as isize { Err(Error::NotEnoughBytes(required_bytes)) @@ -209,6 +251,8 @@ impl<'b> Decoder<'b> { } } + /// Ensures the buffer has the required bits passed in by required_bits. + /// Throws a NotEnoughBits error if there are less bits remaining in the buffer than required_bits. fn ensure_bits(&mut self, required_bits: usize) -> Result<(), Error> { if required_bits as isize > (self.buffer.len() as isize - self.pos as isize) * 8 - self.used_bits as isize @@ -219,12 +263,18 @@ impl<'b> Decoder<'b> { } } + /// Increment buffer by num_bits. + /// If num_bits + used bits is greater than 8, + /// then increment position by (num_bits + used bits) / 8 + /// Use the left over remainder as the new amount of used bits. fn drop_bits(&mut self, num_bits: usize) { let all_used_bits = num_bits as i64 + self.used_bits; self.used_bits = all_used_bits % 8; self.pos += all_used_bits as usize / 8; } + /// Increment used bits by 1. + /// If all 8 bits are used then increment buffer position by 1. fn increment_buffer_by_bit(&mut self) { if self.used_bits == 7 { self.pos += 1;