From fdfaf91bcf5600e610e6871e6ea3bec5c74e286f Mon Sep 17 00:00:00 2001 From: Kasey White Date: Sun, 22 May 2022 18:16:42 -0400 Subject: [PATCH] feat: create encoding for char, string, byte array --- crates/flat/src/encode.rs | 40 ++++++++++++++++++ crates/flat/src/encoder.rs | 86 +++++++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/crates/flat/src/encode.rs b/crates/flat/src/encode.rs index b747278b..c4ccc566 100644 --- a/crates/flat/src/encode.rs +++ b/crates/flat/src/encode.rs @@ -20,6 +20,46 @@ impl Encode for u8 { } } +impl Encode for char { + fn encode(&self, e: &mut Encoder) -> Result<(), String> { + e.char(*self)?; + + Ok(()) + } +} + +impl Encode for &str { + fn encode(&self, e: &mut Encoder) -> Result<(), String> { + e.string(*self)?; + + Ok(()) + } +} + +impl Encode for String { + fn encode(&self, e: &mut Encoder) -> Result<(), String> { + e.string(self)?; + + Ok(()) + } +} + +impl Encode for Vec { + fn encode(&self, e: &mut Encoder) -> Result<(), String> { + e.bytes(self)?; + + Ok(()) + } +} + +impl Encode for &[u8] { + fn encode(&self, e: &mut Encoder) -> Result<(), String> { + e.bytes(self)?; + + Ok(()) + } +} + impl Encode for (T, K) where T: Encode, diff --git a/crates/flat/src/encoder.rs b/crates/flat/src/encoder.rs index 24b2e7a4..229efca0 100644 --- a/crates/flat/src/encoder.rs +++ b/crates/flat/src/encoder.rs @@ -3,7 +3,7 @@ use crate::encode::Encode; pub struct Encoder { pub buffer: Vec, // Int - used_bits: usize, + used_bits: i64, // Int current_byte: u8, } @@ -34,7 +34,7 @@ impl Encoder { self.current_byte = x; self.next_word(); } else { - todo!() + self.byte_unaligned(x); } Ok(self) @@ -49,6 +49,30 @@ impl Encoder { } } + pub fn bytes(&mut self, arr: &[u8]) -> Result<&mut Self, String> { + if self.used_bits != 0 { + return Err("Buffer is not byte aligned".to_string()); + } + self.write_blk(arr, &mut 0); + Ok(self) + } + + pub fn char(&mut self, c: char) -> Result<&mut Self, String> { + self.word(c as u32); + Ok(self) + } + + pub fn string(&mut self, s: &str) -> Result<&mut Self, String> { + for i in s.chars() { + self.one(); + self.char(i)?; + } + + self.zero(); + + Ok(self) + } + fn zero(&mut self) -> &mut Self { if self.used_bits == 7 { self.next_word(); @@ -71,6 +95,13 @@ impl Encoder { self } + fn byte_unaligned(&mut self, x: u8) { + let x_shift = self.current_byte | (x >> self.used_bits); + self.buffer.push(x_shift); + + self.current_byte = x << (8 - self.used_bits); + } + fn next_word(&mut self) { self.buffer.push(self.current_byte); @@ -78,6 +109,57 @@ impl Encoder { self.used_bits = 0; } + fn write_blk(&mut self, arr: &[u8], src_ptr: &mut usize) { + let src_len = arr.len() - *src_ptr; + let blk_len = src_len.min(255); + self.buffer.push(blk_len as u8); + if blk_len == 0 { + return; + } + + self.buffer.extend(&arr[*src_ptr..blk_len]); + + *src_ptr += blk_len; + self.write_blk(arr, src_ptr); + } + + fn word(&mut self, c: u32) { + loop { + let mut w = (c & 127) as u8; + let c = c >> 7; + + if c != 0 { + w |= 128; + } + self.bits(8, w); + + if c == 0 { + break; + } + } + } + + fn bits(&mut self, num_bits: i64, val: u8) { + self.used_bits += num_bits; + let unused_bits = 8 - self.used_bits; + match unused_bits { + x if x > 0 => { + self.current_byte |= val << x; + } + x if x == 0 => { + self.current_byte |= val; + self.next_word(); + } + x => { + let used = -x; + self.current_byte |= val >> used; + self.next_word(); + self.current_byte = val << (8 - used); + self.used_bits = used; + } + } + } + pub(crate) fn filler(&mut self) { self.current_byte |= 1; self.next_word();