diff --git a/Cargo.toml b/Cargo.toml index 6324a91..56bf23b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] +num = "0.4.3" diff --git a/src/bit_buffer.rs b/src/bit_buffer.rs index b9ed89b..10a373e 100644 --- a/src/bit_buffer.rs +++ b/src/bit_buffer.rs @@ -32,7 +32,21 @@ impl BitWriter { } } -trait Poppable { +impl Into> for BitWriter { + fn into(self) -> Vec { + self.flush() + } +} +impl IntoIterator for BitWriter { + type Item = u8; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.flush().into_iter() + } +} + +pub trait Poppable { fn pop(&mut self) -> Option; } impl Poppable for &[u8] { diff --git a/src/modelA.rs b/src/modelA.rs index 5d541bf..b43c9b5 100644 --- a/src/modelA.rs +++ b/src/modelA.rs @@ -11,13 +11,11 @@ use crate::bit_buffer::{BitWriter, Poppable}; trait Digits { const PRECISION: usize; - fn as_byte(&self) -> u8; } macro_rules! unsignedImplDigits { ($($type: ident),*) => { $( impl Digits for $type { const PRECISION: usize = (std::mem::size_of::<$type>() * 8); - fn as_byte(&self) -> u8 {*self as u8} } )* }; } @@ -25,12 +23,11 @@ macro_rules! signedImplDigits { ($($type: ident),*) => { $( impl Digits for $type { const PRECISION: usize = (std::mem::size_of::<$type>() * 8) - 1; - fn as_byte(&self) -> u8 {*self as u8} } )* }; } -unsignedImplDigits!(u16, u32, u64, u128); -signedImplDigits!(i16, i32, i64, i128); +unsignedImplDigits!(u32, u64); +signedImplDigits!(i32, i64, i128); pub trait Metrics: Integer + FromPrimitive + Copy + BitAnd + Shl @@ -39,15 +36,17 @@ pub trait Metrics: const FREQUENCY_BITS: usize = (Self::PRECISION / 2) - 1; const CODE_VALUE_BITS: usize = Self::FREQUENCY_BITS + 2; - const MAX_CODE: usize = (1 << Self::CODE_VALUE_BITS) - 1; + const MAX_CODE: usize = if Self::CODE_VALUE_BITS == 64 { + u64::MAX as usize + } else { + (1 << Self::CODE_VALUE_BITS) - 1 + }; const MAX_FREQ: usize = (1 << Self::FREQUENCY_BITS) - 1; const ONE_FOURTH: usize = 1 << (Self::CODE_VALUE_BITS - 2); const ONE_HALF: usize = 2 * Self::ONE_FOURTH; const THREE_FOURTHS: usize = 3 * Self::ONE_FOURTH; - fn as_byte(&self) -> u8; - fn print_metrics() { println!("--------- Metrics ---------"); println!(" PRECISION: {}", Self::PRECISION); @@ -64,26 +63,8 @@ impl + Shl u8 { - self.as_byte() - } } -/* -const PRECISION: u32 = 32; - -// 15 bits for frequency count -const FREQUENCY_BITS: u32 = (PRECISION / 2) - 1; -// 17 bits for CODE_VALUE -const VALUE_BITS: u32 = FREQUENCY_BITS + 2; - -const MAX_CODE: u32 = !((!0) << VALUE_BITS); -const MAX_FREQ: u32 = !((!0) << FREQUENCY_BITS); -const HALF: u32 = 1 << (VALUE_BITS - 1); -const LOW_CONVERGE: u32 = 0b10 << (VALUE_BITS - 2); -const HIGH_CONVERGE: u32 = 0b01 << (VALUE_BITS - 2); -*/ - #[derive(Debug)] struct Prob { low: T, @@ -123,13 +104,11 @@ impl<'a> InputBits<'a> { } else { self.last_mask >>= 1; } - return (self.current_byte & self.last_mask) != 0; + let bit = (self.current_byte & self.last_mask) != 0; + return bit; } } -//TODO: use unified trait -//trait CodeValue: Metrics + Integer + Into {} - #[derive(Debug)] #[allow(non_camel_case_types)] pub struct ModelA { @@ -151,7 +130,6 @@ impl Default for ModelA { } } -#[allow(dead_code)] #[allow(non_snake_case)] #[allow(non_camel_case_types)] impl ModelA { @@ -220,7 +198,7 @@ impl ModelA { if c > 255 || c < 0 { break; } - output.push(value.as_byte()); + output.push(c as u8); high = low + (range * p.high) / p.total - ONE; low = low + (range * p.low) / p.total; loop { @@ -261,8 +239,6 @@ impl ModelA { for mut c in input.iter().map(|b| *b as i32).chain([256_i32]) { if c > 255 || c < 0 { c = 256; - } else { - println!("c: '{}'", c as u8 as char); } let p = self.getProbability(c); let range: CODE_VALUE = high - low + ONE; @@ -288,7 +264,6 @@ impl ModelA { break; } } - println!("EOF"); pending_bits += 1; if low < ONE_FORTH { Self::write_with_pending(false, &mut pending_bits, &mut output); @@ -296,16 +271,13 @@ impl ModelA { Self::write_with_pending(true, &mut pending_bits, &mut output); } - println!(""); return output.into(); } fn write_with_pending(bit: bool, pending: &mut i32, output: &mut BitWriter) { - print!("{}\n", if bit { "1" } else { "0" }); output.write(bit); for _ in 0..*pending { output.write(!bit); - print!("{}\n", if !bit { "1" } else { "0" }); } *pending = 0; }