Skip to main content

fax/
lib.rs

1#![deny(unsafe_code)]
2use std::convert::Infallible;
3use std::fmt;
4use std::io::{self, Read};
5use std::iter::Map;
6use std::ops::Not;
7
8#[cfg(feature = "debug")]
9macro_rules! debug {
10    ($($arg:expr),*) => (
11        println!($($arg),*)
12    )
13}
14#[cfg(not(feature = "debug"))]
15macro_rules! debug {
16    ($($arg:expr),*) => {
17        ()
18    };
19}
20
21pub mod maps;
22
23/// Decoder module
24pub mod decoder;
25
26/// Encoder module
27pub mod encoder;
28
29/// TIFF helper functions
30pub mod tiff;
31
32/// Trait used to read data bitwise.
33///
34/// For lazy people `ByteReader` is provided which implements this trait.
35pub trait BitReader {
36    type Error;
37
38    /// look at the next (up to 16) bits of data
39    ///
40    /// Data is returned in the lower bits of the `u16`.
41    fn peek(&self, bits: u8) -> Option<u16>;
42
43    /// Consume the given amount of bits from the input.
44    fn consume(&mut self, bits: u8) -> Result<(), Self::Error>;
45
46    /// Assert that the next bits matches the given pattern.
47    ///
48    /// If it does not match, the found pattern is returned if enough bits are aviable.
49    /// Otherwise None is returned.
50    fn expect(&mut self, bits: Bits) -> Result<(), Option<Bits>> {
51        match self.peek(bits.len) {
52            None => Err(None),
53            Some(val) if val == bits.data => Ok(()),
54            Some(val) => Err(Some(Bits {
55                data: val,
56                len: bits.len,
57            })),
58        }
59    }
60
61    fn bits_to_byte_boundary(&self) -> u8;
62}
63
64/// Trait to write data bitwise
65///
66/// The `VecWriter` struct is provided for convinience.
67pub trait BitWriter {
68    type Error;
69    fn write(&mut self, bits: Bits) -> Result<(), Self::Error>;
70}
71pub struct VecWriter {
72    data: Vec<u8>,
73    partial: u32,
74    len: u8,
75}
76impl BitWriter for VecWriter {
77    type Error = Infallible;
78    fn write(&mut self, bits: Bits) -> Result<(), Self::Error> {
79        self.partial |= (bits.data as u32) << (32 - self.len - bits.len);
80        self.len += bits.len;
81        while self.len >= 8 {
82            self.data.push((self.partial >> 24) as u8);
83            self.partial <<= 8;
84            self.len -= 8;
85        }
86        Ok(())
87    }
88}
89impl VecWriter {
90    pub fn new() -> Self {
91        VecWriter {
92            data: Vec::new(),
93            partial: 0,
94            len: 0,
95        }
96    }
97    // with capacity of `n` bits.
98    pub fn with_capacity(n: usize) -> Self {
99        VecWriter {
100            data: Vec::with_capacity((n + 7) / 8),
101            partial: 0,
102            len: 0,
103        }
104    }
105
106    /// Pad the output with `0` bits until it is at a byte boundary.
107    pub fn pad(&mut self) {
108        if self.len > 0 {
109            self.data.push((self.partial >> 24) as u8);
110            self.partial = 0;
111            self.len = 0;
112        }
113    }
114
115    /// pad and return the accumulated bytes
116    pub fn finish(mut self) -> Vec<u8> {
117        self.pad();
118        self.data
119    }
120}
121
122pub struct ByteReader<R> {
123    read: R,
124    partial: u32,
125    valid: u8,
126}
127impl<E, R: Iterator<Item = Result<u8, E>>> ByteReader<R> {
128    /// Construct a new `ByteReader` from an iterator of `u8`
129    pub fn new(read: R) -> Result<Self, E> {
130        let mut bits = ByteReader {
131            read,
132            partial: 0,
133            valid: 0,
134        };
135        bits.fill()?;
136        Ok(bits)
137    }
138    fn fill(&mut self) -> Result<(), E> {
139        while self.valid < 16 {
140            match self.read.next() {
141                Some(Ok(byte)) => {
142                    self.partial = self.partial << 8 | byte as u32;
143                    self.valid += 8;
144                }
145                Some(Err(e)) => return Err(e),
146                None => break,
147            }
148        }
149        Ok(())
150    }
151    /// Print the remaining data
152    ///
153    /// Note: For debug purposes only, not part of the API.
154    pub fn print_remaining(&mut self) {
155        println!(
156            "partial: {:0w$b}, valid: {}",
157            self.partial & ((1 << self.valid) - 1),
158            self.valid,
159            w = self.valid as usize
160        );
161        while let Some(Ok(b)) = self.read.next() {
162            print!("{:08b} ", b);
163        }
164        println!();
165    }
166    pub fn print_peek(&self) {
167        println!(
168            "partial: {:0w$b}, valid: {}",
169            self.partial & ((1 << self.valid) - 1),
170            self.valid,
171            w = self.valid as usize
172        );
173    }
174}
175
176pub fn slice_reader(slice: &[u8]) -> ByteReader<impl Iterator<Item = Result<u8, Infallible>> + '_> {
177    ByteReader::new(slice.iter().cloned().map(Ok)).unwrap()
178}
179pub fn slice_bits(slice: &[u8]) -> impl Iterator<Item = bool> + '_ {
180    slice
181        .iter()
182        .flat_map(|&b| [7, 6, 5, 4, 3, 2, 1, 0].map(|i| (b >> i) & 1 != 0))
183}
184
185impl<E, R: Iterator<Item = Result<u8, E>>> BitReader for ByteReader<R> {
186    type Error = E;
187
188    fn peek(&self, bits: u8) -> Option<u16> {
189        if bits > 16 {
190            return None;
191        }
192        if self.valid >= bits {
193            let shift = self.valid - bits;
194            let mask = if bits >= 16 {
195                u16::MAX
196            } else {
197                (1u16 << bits) - 1
198            };
199            let out = (self.partial >> shift) as u16 & mask;
200            Some(out)
201        } else {
202            None
203        }
204    }
205    fn consume(&mut self, bits: u8) -> Result<(), E> {
206        self.valid = self.valid.saturating_sub(bits);
207        self.fill()
208    }
209    fn bits_to_byte_boundary(&self) -> u8 {
210        self.valid & 7
211    }
212}
213
214#[test]
215fn test_bits() {
216    let mut bits = slice_reader(&[0b0000_1101, 0b1010_0000]);
217    assert_eq!(maps::black::decode(&mut bits), Some(42));
218}
219
220#[test]
221fn test_peek_over_16_returns_none() {
222    let bits = slice_reader(&[0xFF, 0xFF, 0xFF]);
223    // peek(17) should return None, not panic
224    assert_eq!(bits.peek(17), None);
225    assert_eq!(bits.peek(255), None);
226    // peek(16) should still work
227    assert!(bits.peek(16).is_some());
228}
229
230#[test]
231fn test_consume_more_than_valid_saturates() {
232    let mut bits = slice_reader(&[0xAB]);
233    // consume more bits than available — should not panic
234    let _ = bits.consume(200);
235    // after saturating to 0, peek should return None for any nonzero request
236    assert_eq!(bits.peek(1), None);
237}
238
239#[cfg(test)]
240mod tests {
241    use super::*;
242
243    /// Build a Group 3 bitstream from a sequence of bits.
244    fn bits_to_bytes(bits: &[u8]) -> Vec<u8> {
245        let mut bytes = Vec::new();
246        let mut byte = 0u8;
247        let mut count = 0;
248        for &b in bits {
249            byte = (byte << 1) | (b & 1);
250            count += 1;
251            if count == 8 {
252                bytes.push(byte);
253                byte = 0;
254                count = 0;
255            }
256        }
257        if count > 0 {
258            byte <<= 8 - count;
259            bytes.push(byte);
260        }
261        bytes
262    }
263
264    #[test]
265    fn test_group3_all_white_line() {
266        // Build a minimal Group 3 stream:
267        // - Initial EOL (000000000001)
268        // - Line 1: white(8) = 10011, EOL
269        // - RTC: 5 more EOLs
270        let mut stream_bits = Vec::new();
271
272        // Initial EOL
273        let eol: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
274        stream_bits.extend_from_slice(eol);
275
276        // Line 1: white run of 8 pixels = 10011
277        stream_bits.extend_from_slice(&[1, 0, 0, 1, 1]);
278        // EOL after line 1
279        stream_bits.extend_from_slice(eol);
280
281        // RTC: 5 more EOLs
282        for _ in 0..5 {
283            stream_bits.extend_from_slice(eol);
284        }
285
286        let data = bits_to_bytes(&stream_bits);
287        let mut lines = Vec::new();
288        decoder::decode_g3(data.into_iter(), |transitions| {
289            lines.push(transitions.to_vec());
290        });
291
292        assert_eq!(lines.len(), 1, "expected 1 line, got {}", lines.len());
293        // All-white line: single transition at position 8 (white→black at the end)
294        // Actually, the run-length is 8 white pixels. The transitions list shows
295        // color change positions. For an all-white line, there are no transitions
296        // (white runs the full width). But the decoder adds a0 += p after each code,
297        // and pushes a0. For white(8), a0 = 8, pushed once. That's one transition.
298        assert_eq!(lines[0], vec![8]);
299    }
300
301    #[test]
302    fn test_group3_mixed_line() {
303        // Width 16: 4 white, 4 black, 8 white
304        // white(4) = 1011, black(4) = 011, white(8) = 10011
305        let mut stream_bits = Vec::new();
306
307        let eol: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
308
309        // Initial EOL
310        stream_bits.extend_from_slice(eol);
311
312        // Line: white(4)=1011, black(4)=011, white(8)=10011
313        stream_bits.extend_from_slice(&[1, 0, 1, 1]); // white 4
314        stream_bits.extend_from_slice(&[0, 1, 1]); // black 4
315        stream_bits.extend_from_slice(&[1, 0, 0, 1, 1]); // white 8
316        stream_bits.extend_from_slice(eol);
317
318        // RTC
319        for _ in 0..5 {
320            stream_bits.extend_from_slice(eol);
321        }
322
323        let data = bits_to_bytes(&stream_bits);
324        let mut lines = Vec::new();
325        decoder::decode_g3(data.into_iter(), |transitions| {
326            lines.push(transitions.to_vec());
327        });
328
329        assert_eq!(lines.len(), 1);
330        // Transitions: white(4) -> position 4, black(4) -> position 8, white(8) -> position 16
331        assert_eq!(lines[0], vec![4, 8, 16]);
332    }
333
334    #[test]
335    fn test_group3_with_fill_bits() {
336        // T.4 allows 0-7 fill bits (zeros) before each EOL for byte
337        // alignment. Test all fill counts to verify is_eol_ahead detects
338        // fill+EOL without the prefix tree consuming fill bits.
339        let eol: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
340
341        for fill_count in 0u8..=7 {
342            let mut stream_bits = Vec::new();
343
344            // Initial EOL with fill
345            for _ in 0..fill_count {
346                stream_bits.push(0);
347            }
348            stream_bits.extend_from_slice(eol);
349
350            // Line: white(4) = 1011
351            stream_bits.extend_from_slice(&[1, 0, 1, 1]);
352
353            // EOL with fill
354            for _ in 0..fill_count {
355                stream_bits.push(0);
356            }
357            stream_bits.extend_from_slice(eol);
358
359            // RTC: 5 more EOLs with fill
360            for _ in 0..5 {
361                for _ in 0..fill_count {
362                    stream_bits.push(0);
363                }
364                stream_bits.extend_from_slice(eol);
365            }
366
367            let data = bits_to_bytes(&stream_bits);
368            let mut lines = Vec::new();
369            decoder::decode_g3(data.into_iter(), |transitions| {
370                lines.push(transitions.to_vec());
371            });
372
373            assert_eq!(
374                lines.len(),
375                1,
376                "fill={fill_count}: expected 1 line, got {}",
377                lines.len()
378            );
379            assert_eq!(
380                lines[0],
381                vec![4],
382                "fill={fill_count}: expected [4], got {:?}",
383                lines[0]
384            );
385        }
386    }
387
388    #[test]
389    fn test_group3_multiple_lines() {
390        let mut stream_bits = Vec::new();
391        let eol: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
392
393        // Initial EOL
394        stream_bits.extend_from_slice(eol);
395
396        // Line 1: white(4)=1011
397        stream_bits.extend_from_slice(&[1, 0, 1, 1]);
398        stream_bits.extend_from_slice(eol);
399
400        // Line 2: white(8)=10011
401        stream_bits.extend_from_slice(&[1, 0, 0, 1, 1]);
402        stream_bits.extend_from_slice(eol);
403
404        // Line 3: white(2)=0111, black(3)=10
405        stream_bits.extend_from_slice(&[0, 1, 1, 1]); // white 2
406        stream_bits.extend_from_slice(&[1, 0]); // black 3
407        stream_bits.extend_from_slice(eol);
408
409        // RTC
410        for _ in 0..5 {
411            stream_bits.extend_from_slice(eol);
412        }
413
414        let data = bits_to_bytes(&stream_bits);
415        let mut lines = Vec::new();
416        decoder::decode_g3(data.into_iter(), |transitions| {
417            lines.push(transitions.to_vec());
418        });
419
420        assert_eq!(lines.len(), 3);
421        assert_eq!(lines[0], vec![4]);
422        assert_eq!(lines[1], vec![8]);
423        assert_eq!(lines[2], vec![2, 5]); // white 2, then black 3 = positions 2, 5
424    }
425}
426
427/// Enum used to signal black/white.
428#[derive(Copy, Clone, Debug, PartialEq, Eq)]
429pub enum Color {
430    Black,
431    White,
432}
433impl Not for Color {
434    type Output = Self;
435    fn not(self) -> Self {
436        match self {
437            Color::Black => Color::White,
438            Color::White => Color::Black,
439        }
440    }
441}
442
443struct Transitions<'a> {
444    edges: &'a [u16],
445    pos: usize,
446}
447impl<'a> Transitions<'a> {
448    fn new(edges: &'a [u16]) -> Self {
449        Transitions { edges, pos: 0 }
450    }
451    fn seek_back(&mut self, start: u16) {
452        self.pos = self.pos.min(self.edges.len().saturating_sub(1));
453        while self.pos > 0 {
454            if start < self.edges[self.pos - 1] {
455                self.pos -= 1;
456            } else {
457                break;
458            }
459        }
460    }
461    fn next_color(&mut self, start: u16, color: Color, start_of_row: bool) -> Option<u16> {
462        if start_of_row {
463            if color == Color::Black {
464                self.pos = 1;
465                return self.edges.get(0).cloned();
466            } else {
467                self.pos = 2;
468                return self.edges.get(1).cloned();
469            }
470        }
471        while self.pos < self.edges.len() {
472            if self.edges[self.pos] <= start {
473                self.pos += 1;
474                continue;
475            }
476
477            if (self.pos % 2 == 0) != (color == Color::Black) {
478                self.pos += 1;
479            }
480
481            break;
482        }
483        if self.pos < self.edges.len() {
484            let val = self.edges[self.pos];
485            self.pos += 1;
486            Some(val)
487        } else {
488            None
489        }
490    }
491    fn next(&mut self) -> Option<u16> {
492        if self.pos < self.edges.len() {
493            let val = self.edges[self.pos];
494            self.pos += 1;
495            Some(val)
496        } else {
497            None
498        }
499    }
500    fn peek(&self) -> Option<u16> {
501        self.edges.get(self.pos).cloned()
502    }
503    fn skip(&mut self, n: usize) {
504        self.pos += n;
505    }
506}
507
508#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
509pub struct Bits {
510    pub data: u16,
511    pub len: u8,
512}
513
514impl fmt::Debug for Bits {
515    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
516        write!(f, "d={:0b} w={}", self.data, self.len)
517    }
518}
519impl fmt::Display for Bits {
520    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
521        write!(
522            f,
523            "{:0w$b}",
524            self.data & ((1 << self.len) - 1),
525            w = self.len as usize
526        )
527    }
528}