1use crate::bitio::direction::Direction;
9use crate::bitio::small_bit_vec::{SmallBitVec, SmallBitVecReverse};
10use crate::core::marker::PhantomData;
11use crate::core::ops::{Add, Shl};
12use crate::huffman::create_huffman_table;
13#[cfg(not(feature = "std"))]
14use alloc::borrow::ToOwned;
15#[cfg(not(feature = "std"))]
16use alloc::string::String;
17#[cfg(not(feature = "std"))]
18#[allow(unused_imports)]
19use alloc::vec;
20#[cfg(not(feature = "std"))]
21use alloc::vec::Vec;
22use num_traits::{cast, NumCast};
23
24pub(crate) struct HuffmanEncoder<D: Direction, T> {
25 bit_vec_tab: Vec<Option<SmallBitVec<T>>>,
26 phantom: PhantomData<fn() -> D>,
27}
28
29impl<D, T> HuffmanEncoder<D, T>
30where
31 D: Direction,
32 T: Clone + PartialOrd<T> + Shl<u8, Output = T> + Add<Output = T> + From<u8>,
33 SmallBitVec<T>: SmallBitVecReverse,
34{
35 pub(crate) fn new(symb_len: &[u8]) -> Self {
36 Self {
37 bit_vec_tab: create_huffman_table(symb_len, D::is_reverse()),
38 phantom: PhantomData,
39 }
40 }
41
42 pub(crate) fn enc<U: NumCast + Clone>(
43 &self,
44 data: U,
45 ) -> Result<SmallBitVec<T>, String> {
46 if let Some(idx) = cast::<_, usize>(data.clone()) {
47 if idx < self.bit_vec_tab.len() {
48 if let Some(ref bv) = self.bit_vec_tab[idx] {
49 return Ok(bv.clone());
50 }
51 }
52 }
53 Err("out of value(huffman encodeing)".to_owned())
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::bitio::direction::left::Left;
61 use crate::bitio::direction::right::Right;
62
63 #[test]
64 fn lefthuffman_encode_new() {
65 let hencoder =
66 HuffmanEncoder::<Left, u16>::new(&[0_u8, 4, 4, 4, 4, 3, 3, 2, 2]);
67 let tab = hencoder.bit_vec_tab;
68
69 assert_eq!(tab[0], None);
70 assert_eq!(tab[1], Some(SmallBitVec::new(0b1100, 4)));
71 assert_eq!(tab[2], Some(SmallBitVec::new(0b1101, 4)));
72 assert_eq!(tab[3], Some(SmallBitVec::new(0b1110, 4)));
73 assert_eq!(tab[4], Some(SmallBitVec::new(0b1111, 4)));
74 assert_eq!(tab[5], Some(SmallBitVec::new(0b100, 3)));
75 assert_eq!(tab[6], Some(SmallBitVec::new(0b101, 3)));
76 assert_eq!(tab[7], Some(SmallBitVec::new(0b00, 2)));
77 assert_eq!(tab[8], Some(SmallBitVec::new(0b01, 2)));
78 assert_eq!(tab.len(), 9);
79 }
80
81 #[test]
82 fn lefthuffman_encode_write() {
83 let hencoder =
84 HuffmanEncoder::<Left, u16>::new(&[0_u8, 4, 4, 4, 4, 3, 3, 2, 2]);
85
86 assert_eq!(
87 hencoder.enc(b'a' - 0x60).ok(),
88 Some(SmallBitVec::new(0b1100, 4))
89 );
90 assert_eq!(
91 hencoder.enc(b'b' - 0x60).ok(),
92 Some(SmallBitVec::new(0b1101, 4))
93 );
94 assert_eq!(
95 hencoder.enc(b'c' - 0x60).ok(),
96 Some(SmallBitVec::new(0b1110, 4))
97 );
98 assert_eq!(
99 hencoder.enc(b'd' - 0x60).ok(),
100 Some(SmallBitVec::new(0b1111, 4))
101 );
102 assert_eq!(
103 hencoder.enc(b'e' - 0x60).ok(),
104 Some(SmallBitVec::new(0b100, 3))
105 );
106 assert_eq!(
107 hencoder.enc(b'f' - 0x60).ok(),
108 Some(SmallBitVec::new(0b101, 3))
109 );
110 assert_eq!(
111 hencoder.enc(b'g' - 0x60).ok(),
112 Some(SmallBitVec::new(0b00, 2))
113 );
114 assert_eq!(
115 hencoder.enc(b'h' - 0x60).ok(),
116 Some(SmallBitVec::new(0b01, 2))
117 );
118 }
119
120 #[test]
121 fn lefthuffman_encode_new_zero() {
122 let hencoder =
123 HuffmanEncoder::<Left, u16>::new(&[0_u8, 0_u8, 0_u8, 0_u8]);
124 let tab = hencoder.bit_vec_tab;
125
126 assert_eq!(tab.len(), 0);
127 }
128
129 #[test]
130 fn lefthuffman_encode_all() {
131 let hencoder = HuffmanEncoder::<Left, u16>::new(&[8; 256]);
132 let tab = hencoder.bit_vec_tab;
133
134 for i in 0..256 {
135 assert_eq!(tab[i as usize], Some(SmallBitVec::new(i, 8)));
136 }
137 assert_eq!(tab.len(), 256);
138 }
139
140 #[test]
141 fn righthuffman_encode_new() {
142 let hencoder =
143 HuffmanEncoder::<Right, u16>::new(&[0_u8, 4, 4, 4, 4, 3, 3, 2, 2]);
144 let tab = hencoder.bit_vec_tab;
145
146 assert_eq!(tab[0], None);
147 assert_eq!(tab[1], Some(SmallBitVec::new(0b0011, 4)));
148 assert_eq!(tab[2], Some(SmallBitVec::new(0b1011, 4)));
149 assert_eq!(tab[3], Some(SmallBitVec::new(0b0111, 4)));
150 assert_eq!(tab[4], Some(SmallBitVec::new(0b1111, 4)));
151 assert_eq!(tab[5], Some(SmallBitVec::new(0b001, 3)));
152 assert_eq!(tab[6], Some(SmallBitVec::new(0b101, 3)));
153 assert_eq!(tab[7], Some(SmallBitVec::new(0b00, 2)));
154 assert_eq!(tab[8], Some(SmallBitVec::new(0b10, 2)));
155 assert_eq!(tab.len(), 9);
156 }
157
158 #[test]
159 fn righthuffman_encode_write() {
160 let hencoder =
161 HuffmanEncoder::<Right, u16>::new(&[0_u8, 4, 4, 4, 4, 3, 3, 2, 2]);
162
163 assert_eq!(
164 b"abcdefgh"
165 .iter()
166 .map(|x| x - 0x60)
167 .map(|x| hencoder.enc(x).unwrap())
168 .collect::<Vec<_>>(),
169 vec![
170 SmallBitVec::new(0b0011, 4),
171 SmallBitVec::new(0b1011, 4),
172 SmallBitVec::new(0b0111, 4),
173 SmallBitVec::new(0b1111, 4),
174 SmallBitVec::new(0b001, 3),
175 SmallBitVec::new(0b101, 3),
176 SmallBitVec::new(0b00, 2),
177 SmallBitVec::new(0b10, 2),
178 ]
179 );
180 }
181
182 #[test]
183 fn righthuffman_encode_new_zero() {
184 let hencoder = HuffmanEncoder::<Right, u16>::new(&[0_u8, 0, 0, 0]);
185 let tab = hencoder.bit_vec_tab;
186
187 assert_eq!(tab.len(), 0);
188 }
189}