deflate/
bitstream.rs

1// This was originally based on code from: https://github.com/nwin/lzw
2// Copyright (c) 2015 nwin
3// which is under both Apache 2.0 and MIT
4
5//! This module provides a bit writer
6use std::io::{self, Write};
7
8#[cfg(target_pointer_width = "64")]
9#[macro_use]
10mod arch_dep {
11    /// The data type of the accumulator.
12    /// a 64-bit value allows us to store more before
13    /// each push to the vector, but is sub-optimal
14    /// on 32-bit platforms.
15    pub type AccType = u64;
16    pub const FLUSH_AT: u8 = 48;
17    /// Push pending bits to vector.
18    /// Using a macro here since an inline function.
19    /// didn't optimise properly.
20    /// TODO June 2019: See if it's still needed.
21    macro_rules! push {
22        ($s:ident) => {
23            $s.w.extend_from_slice(
24                &[
25                    $s.acc as u8,
26                    ($s.acc >> 8) as u8,
27                    ($s.acc >> 16) as u8,
28                    ($s.acc >> 24) as u8,
29                    ($s.acc >> 32) as u8,
30                    ($s.acc >> 40) as u8,
31                ][..],
32            )
33        };
34    }
35}
36#[cfg(not(target_pointer_width = "64"))]
37#[macro_use]
38mod arch_dep {
39    pub type AccType = u32;
40    pub const FLUSH_AT: u8 = 16;
41    macro_rules! push {
42        ($s:ident) => {
43            // Unlike the 64-bit case, using copy_from_slice seemed to worsen performance here.
44            // TODO: Needs benching on a 32-bit system to see what works best.
45            $s.w.push($s.acc as u8);
46            $s.w.push(($s.acc >> 8) as u8);
47        };
48    }
49}
50
51use self::arch_dep::*;
52
53/// Writes bits to a byte stream, LSB first.
54pub struct LsbWriter {
55    // Public for now so it can be replaced after initialization.
56    pub w: Vec<u8>,
57    bits: u8,
58    acc: AccType,
59}
60
61impl LsbWriter {
62    /// Creates a new bit reader
63    pub const fn new(writer: Vec<u8>) -> LsbWriter {
64        LsbWriter {
65            w: writer,
66            bits: 0,
67            acc: 0,
68        }
69    }
70
71    pub const fn pending_bits(&self) -> u8 {
72        self.bits
73    }
74
75    /// Buffer n number of bits, and write them to the vec if there are enough pending bits.
76    pub fn write_bits(&mut self, v: u16, n: u8) {
77        // NOTE: This outputs garbage data if n is 0, but v is not 0
78        self.acc |= (AccType::from(v)) << self.bits;
79        self.bits += n;
80        // Waiting until we have FLUSH_AT bits and pushing them all in one batch.
81        while self.bits >= FLUSH_AT {
82            push!(self);
83            self.acc >>= FLUSH_AT;
84            self.bits -= FLUSH_AT;
85        }
86    }
87
88    fn write_bits_finish(&mut self, v: u16, n: u8) {
89        // NOTE: This outputs garbage data if n is 0, but v is not 0
90        self.acc |= (AccType::from(v)) << self.bits;
91        self.bits += n % 8;
92        while self.bits >= 8 {
93            self.w.push(self.acc as u8);
94            self.acc >>= 8;
95            self.bits -= 8;
96        }
97    }
98
99    pub fn flush_raw(&mut self) {
100        let missing = FLUSH_AT - self.bits;
101        // Have to test for self.bits > 0 here,
102        // otherwise flush would output an extra byte when flush was called at a byte boundary
103        if missing > 0 && self.bits > 0 {
104            self.write_bits_finish(0, missing);
105        }
106    }
107}
108
109impl Write for LsbWriter {
110    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
111        if self.acc == 0 {
112            self.w.extend_from_slice(buf)
113        } else {
114            for &byte in buf.iter() {
115                self.write_bits(u16::from(byte), 8)
116            }
117        }
118        Ok(buf.len())
119    }
120
121    fn flush(&mut self) -> io::Result<()> {
122        self.flush_raw();
123        Ok(())
124    }
125}
126
127#[cfg(test)]
128mod test {
129    use super::LsbWriter;
130
131    #[test]
132    fn write_bits() {
133        let input = [
134            (3, 3),
135            (10, 8),
136            (88, 7),
137            (0, 2),
138            (0, 5),
139            (0, 0),
140            (238, 8),
141            (126, 8),
142            (161, 8),
143            (10, 8),
144            (238, 8),
145            (174, 8),
146            (126, 8),
147            (174, 8),
148            (65, 8),
149            (142, 8),
150            (62, 8),
151            (10, 8),
152            (1, 8),
153            (161, 8),
154            (78, 8),
155            (62, 8),
156            (158, 8),
157            (206, 8),
158            (10, 8),
159            (64, 7),
160            (0, 0),
161            (24, 5),
162            (0, 0),
163            (174, 8),
164            (126, 8),
165            (193, 8),
166            (174, 8),
167        ];
168        let expected = [
169            83, 192, 2, 220, 253, 66, 21, 220, 93, 253, 92, 131, 28, 125, 20, 2, 66, 157, 124, 60,
170            157, 21, 128, 216, 213, 47, 216, 21,
171        ];
172        let mut writer = LsbWriter::new(Vec::new());
173        for v in input.iter() {
174            writer.write_bits(v.0, v.1);
175        }
176        writer.flush_raw();
177        assert_eq!(writer.w, expected);
178    }
179}
180
181#[cfg(all(test, feature = "benchmarks"))]
182mod bench {
183    use super::LsbWriter;
184    use test_std::Bencher;
185    #[bench]
186    fn bit_writer(b: &mut Bencher) {
187        let input = [
188            (3, 3),
189            (10, 8),
190            (88, 7),
191            (0, 2),
192            (0, 5),
193            (0, 0),
194            (238, 8),
195            (126, 8),
196            (161, 8),
197            (10, 8),
198            (238, 8),
199            (174, 8),
200            (126, 8),
201            (174, 8),
202            (65, 8),
203            (142, 8),
204            (62, 8),
205            (10, 8),
206            (1, 8),
207            (161, 8),
208            (78, 8),
209            (62, 8),
210            (158, 8),
211            (206, 8),
212            (10, 8),
213            (64, 7),
214            (0, 0),
215            (24, 5),
216            (0, 0),
217            (174, 8),
218            (126, 8),
219            (193, 8),
220            (174, 8),
221        ];
222        let mut writer = LsbWriter::new(Vec::with_capacity(100));
223        b.iter(|| {
224            for v in input.iter() {
225                let _ = writer.write_bits(v.0, v.1);
226            }
227        });
228    }
229}