From 4fb508e3b2ca86af2d6792ed59f4ddc6235ed312 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Mon, 30 May 2022 02:32:39 -0400 Subject: [PATCH] Add decoding for bytestring, string, char, bool, and filler --- crates/flat/src/decode.rs | 34 ++++++++-- crates/flat/src/decoder.rs | 134 +++++++++++++++++++++++++++++++++++-- crates/flat/src/lib.rs | 2 +- crates/uplc/src/flat.rs | 9 ++- 4 files changed, 163 insertions(+), 16 deletions(-) diff --git a/crates/flat/src/decode.rs b/crates/flat/src/decode.rs index a9affaef..92031d56 100644 --- a/crates/flat/src/decode.rs +++ b/crates/flat/src/decode.rs @@ -1,11 +1,37 @@ use crate::{decoder::Decoder, filler::Filler}; pub trait Decode<'b>: Sized { - fn decode(d: &mut Decoder<'b>) -> Result; + fn decode(d: &mut Decoder) -> Result; } -impl<'b> Decode<'b> for Filler { - fn decode(d: &mut Decoder<'b>) -> Result { - todo!() +impl Decode<'_> for Filler { + fn decode(d: &mut Decoder) -> Result { + d.filler()?; + Ok(Filler::FillerEnd) + } +} + +impl Decode<'_> for Vec { + fn decode(d: &mut Decoder) -> Result { + d.bytes() + } +} + +impl Decode<'_> for char { + fn decode(d: &mut Decoder) -> Result { + d.char() + } +} + +impl Decode<'_> for String { + fn decode(d: &mut Decoder) -> Result { + d.string() + } +} + +impl Decode<'_> for bool { + fn decode(d: &mut Decoder) -> Result { + let b = d.bool(); + Ok(b) } } diff --git a/crates/flat/src/decoder.rs b/crates/flat/src/decoder.rs index 6923528d..7e9eedd2 100644 --- a/crates/flat/src/decoder.rs +++ b/crates/flat/src/decoder.rs @@ -1,21 +1,143 @@ use crate::decode::Decode; -pub struct Decoder<'b> { - buffer: &'b [u8], +pub struct Decoder { + buffer: Vec, used_bits: i64, pos: usize, } -impl<'b> Decoder<'b> { - pub fn new(bytes: &'b [u8]) -> Decoder<'b> { +impl Decoder { + pub fn new(bytes: &[u8]) -> Decoder { Decoder { - buffer: bytes, + buffer: bytes.to_vec(), pos: 0, used_bits: 0, } } - pub fn decode>(&mut self) -> Result { + pub fn decode<'b, T: Decode<'b>>(&mut self) -> Result { T::decode(self) } + + pub fn bool(&mut self) -> bool { + let current_byte = self.buffer[self.pos]; + let b = 0 != (current_byte & (128 >> self.used_bits)); + self.increment_buffer_by_bit(); + b + } + + pub fn bytes(&mut self) -> Result, String> { + self.filler()?; + self.byte_array() + } + + pub fn char(&mut self) -> Result { + Ok(char::from_u32(self.word()? as u32).unwrap()) + } + + pub fn string(&mut self) -> Result { + let mut s = String::new(); + while self.bit()? { + s += &self.char()?.to_string(); + } + Ok(s) + } + + pub fn filler(&mut self) -> Result<(), String> { + while self.zero()? {} + Ok(()) + } + + 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 + while leading_bit == 1 { + let word8 = self.bits8(8)?; + let word7 = word8 & 127; + final_word |= (word7 as usize) << shl; + shl += 7; + leading_bit = word8 & 128; + } + Ok(final_word) + } + + fn zero(&mut self) -> Result { + let current_bit = self.bit()?; + Ok(!current_bit) + } + + fn bit(&mut self) -> Result { + if self.pos >= self.buffer.len() { + return Err("DecoderState: Reached end of buffer".to_string()); + } + let b = self.buffer[self.pos] & (128 >> self.used_bits) > 0; + self.increment_buffer_by_bit(); + Ok(b) + } + + fn byte_array(&mut self) -> Result, String> { + if self.used_bits != 0 { + return Err("DecoderState.byteArray: Buffer is not byte aligned".to_string()); + } + self.ensure_bytes(1)?; + let mut blk_len = self.buffer[self.pos]; + self.pos += 1; + let mut blk_array: Vec = Vec::new(); + while blk_len != 0 { + self.ensure_bytes(blk_len as usize + 1)?; + let decoded_array = &self.buffer[self.pos..self.pos + blk_len as usize]; + blk_array.extend(decoded_array); + self.pos += blk_len as usize; + blk_len = self.buffer[self.pos]; + } + Ok(blk_array) + } + + // can decode up to a max of 8 bits + pub fn bits8(&mut self, num_bits: usize) -> Result { + if num_bits > 8 { + return Err( + "Decoder.bits8: incorrect value of num_bits - must be less than 9".to_string(), + ); + } + self.ensure_bytes(num_bits)?; + let unused_bits = 8 - self.used_bits as usize; + let leading_zeroes = 8 - num_bits; + let r = (self.buffer[self.pos] << self.used_bits as usize) >> leading_zeroes; + + let x = if num_bits > unused_bits { + r | (self.buffer[self.pos + 1] >> (unused_bits + leading_zeroes)) + } else { + r + }; + self.drop_bits(8); + Ok(x) + } + + fn ensure_bytes(&mut self, required_bytes: usize) -> Result<(), String> { + if required_bytes > self.buffer.len() - self.pos { + return Err(format!( + "DecoderState: Not enough data available: {:#?} - required bytes {}", + self.buffer, required_bytes + )); + } + Ok(()) + } + + 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; + } + + fn increment_buffer_by_bit(&mut self) { + if self.used_bits == 7 { + self.pos += 1; + self.used_bits = 0; + } else { + self.used_bits += 1; + } + } } diff --git a/crates/flat/src/lib.rs b/crates/flat/src/lib.rs index 8a11995b..d61d11d1 100644 --- a/crates/flat/src/lib.rs +++ b/crates/flat/src/lib.rs @@ -37,7 +37,7 @@ where Ok(e.buffer) } -pub fn decode<'b, T>(bytes: &'b [u8]) -> Result +pub fn decode<'b, T>(bytes: &[u8]) -> Result where T: de::Decode<'b>, { diff --git a/crates/uplc/src/flat.rs b/crates/uplc/src/flat.rs index 98140447..5fc020f9 100644 --- a/crates/uplc/src/flat.rs +++ b/crates/uplc/src/flat.rs @@ -48,7 +48,7 @@ impl Encode for Program { } impl<'b> Decode<'b> for Program { - fn decode(_d: &mut Decoder<'b>) -> Result { + fn decode(_d: &mut Decoder) -> Result { todo!() } } @@ -91,7 +91,6 @@ impl Encode for Term { Term::Error => { encode_term_tag(6, e)?; - todo!() } Term::Builtin(builtin) => { encode_term_tag(7, e)?; @@ -105,7 +104,7 @@ impl Encode for Term { } impl<'b> Decode<'b> for Term { - fn decode(_d: &mut Decoder<'b>) -> Result { + fn decode(_d: &mut Decoder) -> Result { todo!() } } @@ -147,7 +146,7 @@ impl Encode for &Constant { } impl<'b> Decode<'b> for Constant { - fn decode(_d: &mut Decoder<'b>) -> Result { + fn decode(_d: &mut Decoder) -> Result { todo!() } } @@ -161,7 +160,7 @@ impl Encode for DefaultFunction { } impl<'b> Decode<'b> for DefaultFunction { - fn decode(_d: &mut Decoder<'b>) -> Result { + fn decode(_d: &mut Decoder) -> Result { todo!() } }