Skip to main content

compactly/v2/
byte.rs

1use super::{Encode, EncodingStrategy};
2use crate::{Incompressible, Small};
3
4#[derive(Clone)]
5pub struct ByteContext([<bool as Encode>::Context; 256]);
6impl Default for ByteContext {
7    #[inline]
8    fn default() -> Self {
9        ByteContext([Default::default(); 256])
10    }
11}
12
13impl Encode for u8 {
14    type Context = ByteContext;
15    #[inline]
16    fn encode<E: super::EntropyCoder>(&self, writer: &mut E, ctx: &mut Self::Context) {
17        let mut filled_up = 0;
18        let mut accumulated_value = 0;
19        for i in 0..8 {
20            let ctx = &mut ctx.0[filled_up + accumulated_value];
21            let bit = (*self >> (7 - i)) & 1 == 1;
22            bit.encode(writer, ctx);
23            filled_up += 1 << i;
24            accumulated_value = 2 * accumulated_value + bit as usize;
25        }
26    }
27    #[inline]
28    fn decode<D: super::EntropyDecoder>(
29        reader: &mut D,
30        ctx: &mut Self::Context,
31    ) -> Result<Self, std::io::Error> {
32        let mut filled_up = 0;
33        let mut accumulated_value = 0;
34        for i in 0..8 {
35            let ctx = &mut ctx.0[filled_up + accumulated_value];
36            let bit = bool::decode(reader, ctx)?;
37            filled_up += 1 << i;
38            accumulated_value = 2 * accumulated_value + bit as usize;
39        }
40        Ok(accumulated_value as u8)
41    }
42}
43
44macro_rules! small_num {
45    ($t:ty, $nbits:literal, $maxval:literal, $doublemax:literal, $testname:ident) => {
46        mod $testname {
47            use super::{Encode, UBits};
48
49            #[derive(Clone)]
50            pub struct Context([<bool as Encode>::Context; $doublemax]);
51
52            impl Default for Context {
53                #[inline]
54                fn default() -> Self {
55                    Self([Default::default(); $doublemax])
56                }
57            }
58
59            impl Encode for $t {
60                type Context = Context;
61                #[inline]
62                fn encode<E: super::super::EntropyCoder>(
63                    &self,
64                    writer: &mut E,
65                    ctx: &mut Self::Context,
66                ) {
67                    let value = u8::from(*self);
68                    let mut filled_up = 0;
69                    let mut accumulated_value = 0;
70                    for i in 0..$nbits {
71                        let ctx = &mut ctx.0[filled_up + accumulated_value];
72                        let bit = (value >> ($nbits - 1 - i)) & 1 == 1;
73                        bit.encode(writer, ctx);
74                        filled_up += 1 << i;
75                        accumulated_value = 2 * accumulated_value + bit as usize;
76                    }
77                }
78                #[inline]
79                fn decode<D: super::super::EntropyDecoder>(
80                    reader: &mut D,
81                    ctx: &mut Self::Context,
82                ) -> Result<Self, std::io::Error> {
83                    let mut filled_up = 0;
84                    let mut accumulated_value = 0;
85                    for i in 0..$nbits {
86                        let ctx = &mut ctx.0[filled_up + accumulated_value];
87                        let bit = bool::decode(reader, ctx)?;
88                        filled_up += 1 << i;
89                        accumulated_value = 2 * accumulated_value + bit as usize;
90                    }
91                    Ok((accumulated_value as u8).try_into().unwrap())
92                }
93            }
94
95            #[test]
96            fn test() {
97                for value in 0u8..=$maxval {
98                    println!("Testing {value}");
99                    let v: $t = value.try_into().unwrap();
100                    let encoded = super::super::encode(&v);
101                    let decoded = super::super::decode::<$t>(&encoded).unwrap();
102                    assert_eq!(v, decoded);
103                    assert_eq!(v.millibits(), super::super::Millibits::bits($nbits));
104                }
105            }
106        }
107    };
108}
109
110/// An N-Bit unsigned number that fits into a `u8`.
111///
112/// This number is tracked precisely, like `u8` itself.
113#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
114pub struct UBits<const N: u8>(u8);
115
116impl<const N: u8> From<UBits<N>> for u8 {
117    fn from(value: UBits<N>) -> u8 {
118        value.0
119    }
120}
121
122impl<const N: u8> TryFrom<u8> for UBits<N> {
123    type Error = ();
124    fn try_from(value: u8) -> Result<Self, Self::Error> {
125        if N == 8 {
126            Ok(Self(value))
127        } else if value >> N == 0 {
128            Ok(Self(value))
129        } else {
130            Err(())
131        }
132    }
133}
134
135small_num!(UBits<1>, 1, 1, 2, ub1);
136small_num!(UBits<2>, 2, 3, 4, ub2);
137small_num!(UBits<3>, 3, 7, 8, ub3);
138small_num!(UBits<4>, 4, 15, 16, ub4);
139small_num!(UBits<5>, 5, 31, 32, ub5);
140small_num!(UBits<6>, 6, 63, 64, ub6);
141small_num!(UBits<7>, 7, 127, 128, ub7);
142small_num!(UBits<8>, 8, 255, 256, ub8);
143
144impl Encode for i8 {
145    type Context = <u8 as Encode>::Context;
146    #[inline]
147    fn encode<E: super::EntropyCoder>(&self, writer: &mut E, ctx: &mut Self::Context) {
148        (*self as u8).encode(writer, ctx)
149    }
150    #[inline]
151    fn decode<D: super::EntropyDecoder>(
152        reader: &mut D,
153        ctx: &mut Self::Context,
154    ) -> Result<Self, std::io::Error> {
155        <u8 as Encode>::decode(reader, ctx).map(|v| v as i8)
156    }
157}
158
159#[derive(Default, Clone)]
160pub struct SmallContext {
161    nonzero: <UBits<3> as Encode>::Context,
162    b1: <UBits<1> as Encode>::Context,
163    b2: <UBits<2> as Encode>::Context,
164    b3: <UBits<3> as Encode>::Context,
165    b4: <UBits<4> as Encode>::Context,
166    b5: <UBits<5> as Encode>::Context,
167    need_seven_bits: <bool as Encode>::Context,
168    b6: <UBits<6> as Encode>::Context,
169    b7: <UBits<7> as Encode>::Context,
170}
171
172impl EncodingStrategy<u8> for Small {
173    type Context = SmallContext;
174    fn encode<E: super::EntropyCoder>(value: &u8, writer: &mut E, ctx: &mut Self::Context) {
175        let nonzero: UBits<3>;
176        match *value {
177            0 => {
178                nonzero = 0.try_into().unwrap();
179                nonzero.encode(writer, &mut ctx.nonzero)
180            }
181            1 => {
182                nonzero = 1.try_into().unwrap();
183                nonzero.encode(writer, &mut ctx.nonzero)
184            }
185            2..4 => {
186                nonzero = 2.try_into().unwrap();
187                nonzero.encode(writer, &mut ctx.nonzero);
188                let b1: UBits<1> = (*value - 2).try_into().unwrap();
189                b1.encode(writer, &mut ctx.b1)
190            }
191            4..8 => {
192                nonzero = 3.try_into().unwrap();
193                nonzero.encode(writer, &mut ctx.nonzero);
194                let b2: UBits<2> = (*value - 4).try_into().unwrap();
195                b2.encode(writer, &mut ctx.b2)
196            }
197            8..16 => {
198                nonzero = 4.try_into().unwrap();
199                nonzero.encode(writer, &mut ctx.nonzero);
200                let b3: UBits<3> = (*value - 8).try_into().unwrap();
201                b3.encode(writer, &mut ctx.b3)
202            }
203            16..32 => {
204                nonzero = 5.try_into().unwrap();
205                nonzero.encode(writer, &mut ctx.nonzero);
206                let b4: UBits<4> = (*value - 16).try_into().unwrap();
207                b4.encode(writer, &mut ctx.b4)
208            }
209            32..64 => {
210                nonzero = 6.try_into().unwrap();
211                nonzero.encode(writer, &mut ctx.nonzero);
212                let b5: UBits<5> = (*value - 32).try_into().unwrap();
213                b5.encode(writer, &mut ctx.b5)
214            }
215            64..128 => {
216                nonzero = 7.try_into().unwrap();
217                nonzero.encode(writer, &mut ctx.nonzero);
218                false.encode(writer, &mut ctx.need_seven_bits);
219                let b6: UBits<6> = (*value - 64).try_into().unwrap();
220                b6.encode(writer, &mut ctx.b6)
221            }
222            128..=255 => {
223                nonzero = 7.try_into().unwrap();
224                nonzero.encode(writer, &mut ctx.nonzero);
225                true.encode(writer, &mut ctx.need_seven_bits);
226                let b7: UBits<7> = (*value - 128).try_into().unwrap();
227                b7.encode(writer, &mut ctx.b7)
228            }
229        }
230    }
231    fn decode<D: super::EntropyDecoder>(
232        reader: &mut D,
233        ctx: &mut Self::Context,
234    ) -> Result<u8, std::io::Error> {
235        let nonzero: u8 = <UBits<3> as Encode>::decode(reader, &mut ctx.nonzero)?.into();
236        match nonzero {
237            0 => Ok(0),
238            1 => Ok(1),
239            2 => {
240                let rest: u8 = <UBits<1> as Encode>::decode(reader, &mut ctx.b1)?.into();
241                Ok(rest + 2)
242            }
243            3 => {
244                let rest: u8 = <UBits<2> as Encode>::decode(reader, &mut ctx.b2)?.into();
245                Ok(rest + 4)
246            }
247            4 => {
248                let rest: u8 = <UBits<3> as Encode>::decode(reader, &mut ctx.b3)?.into();
249                Ok(rest + 8)
250            }
251            5 => {
252                let rest: u8 = <UBits<4> as Encode>::decode(reader, &mut ctx.b4)?.into();
253                Ok(rest + 16)
254            }
255            6 => {
256                let rest: u8 = <UBits<5> as Encode>::decode(reader, &mut ctx.b5)?.into();
257                Ok(rest + 32)
258            }
259            7 => {
260                if <bool as Encode>::decode(reader, &mut ctx.need_seven_bits)? {
261                    let rest: u8 = <UBits<7> as Encode>::decode(reader, &mut ctx.b7)?.into();
262                    Ok(rest + 128)
263                } else {
264                    let rest: u8 = <UBits<6> as Encode>::decode(reader, &mut ctx.b6)?.into();
265                    Ok(rest + 64)
266                }
267            }
268            _ => unreachable!(),
269        }
270    }
271}
272
273impl EncodingStrategy<u8> for Incompressible {
274    type Context = ();
275    fn encode<E: super::EntropyCoder>(value: &u8, writer: &mut E, _ctx: &mut Self::Context) {
276        writer.encode_incompressible_bytes(&[*value])
277    }
278    fn decode<D: super::EntropyDecoder>(
279        reader: &mut D,
280        _ctx: &mut Self::Context,
281    ) -> Result<u8, std::io::Error> {
282        let mut byte = [0u8];
283        reader.decode_incompressible_bytes(&mut byte)?;
284        Ok(byte[0])
285    }
286}
287
288#[test]
289fn size() {
290    use super::assert_bits;
291    assert_bits!(u8::MAX, 3);
292    assert_bits!(0_u8, 8);
293    for b in 3_u8..255 {
294        println!("Byte {b}");
295        assert_bits!(b, 8);
296    }
297    assert_bits!(*b"hello", 31);
298    assert_bits!(*b"hello world", 68);
299    assert_bits!(*b"hello world, hello world", 129);
300    assert_bits!(*b"hello hello, hello hello", 111);
301    assert_bits!(*b"hello hello, hello hello, hello hello, hello hello", 195);
302    assert_bits!(*b"hhhhhhhhhhhhhhhhhhhhhhhh", 37);
303    assert_bits!(*b"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", 44);
304    assert_bits!(*b"\0", 8);
305    assert_bits!(*b"\x01", 8);
306    assert_bits!(*b"\x01\x01", 13);
307    assert_bits!(*b"\x01\x01\x01\x01", 19);
308    assert_bits!(*b"\x01\x01\x01\x01\x01", 21);
309    assert_bits!(*b"\x01\x01\x01\x01\x01\x01", 22);
310    assert_bits!(*b"\x01\x02\x03\x04", 25);
311    assert_bits!(*b"\x01\x02\x03\x04\x05", 30);
312    assert_bits!(*b"\x01\x02\x03\x04\x05\x06", 36);
313    assert_bits!(*b"\x01\x02\x03\x04\x05\x06\x07", 40);
314    assert_bits!(*b"\x01\x02\x03\x04\x05\x06\x07\x08", 47);
315
316    assert_bits!(i8::MAX, 8);
317    assert_bits!(0_i8, 8);
318}
319
320#[test]
321fn small() {
322    use super::{assert_bits, Small};
323    use crate::Encoded;
324    fn check_size(v: u8, expected: usize) {
325        println!("Checking {v}");
326        assert_eq!(
327            Encoded::<u8, Small>::new(v).millibits(),
328            super::Millibits::bits(expected)
329        );
330        assert_bits!(Encoded::<u8, Small>::new(v), expected);
331    }
332
333    for x in 0..2 {
334        check_size(x, 3);
335    }
336    for x in 2..4 {
337        check_size(x, 4);
338    }
339    for x in 4..8 {
340        check_size(x, 5);
341    }
342    for x in 8..16 {
343        check_size(x, 6);
344    }
345    for x in 16..32 {
346        check_size(x, 7);
347    }
348    for x in 32..64 {
349        check_size(x, 8);
350    }
351    for x in 64..128 {
352        check_size(x, 10);
353    }
354    for x in 128..255 {
355        check_size(x, 11);
356    }
357    assert_eq!(
358        Encoded::<u8, Small>::new(255u8).millibits(),
359        super::Millibits::bits(11)
360    );
361}