Skip to main content

ppmd_rust/
decoder_7a.rs

1use std::io::Read;
2
3use crate::{
4    internal::ppmd7::{PPMd7, RangeDecoder7a},
5    Error, PPMD7_MAX_MEM_SIZE, PPMD7_MAX_ORDER, PPMD7_MIN_MEM_SIZE, PPMD7_MIN_ORDER, SYM_END,
6};
7
8/// A decoder to decompress data using PPMd7 (PPMdH) with the carryless range coder (PPMd7a).
9pub struct Ppmd7aDecoder<R: Read> {
10    ppmd: PPMd7<RangeDecoder7a<R>>,
11    finished: bool,
12}
13
14impl<R: Read> Ppmd7aDecoder<R> {
15    /// Creates a new [`Ppmd7aDecoder`] which provides a reader over the uncompressed data.
16    ///
17    /// The given `order` must be between [`PPMD7_MIN_ORDER`] and [`PPMD7_MAX_ORDER`]
18    /// The given `mem_size` must be between [`PPMD7_MIN_MEM_SIZE`] and [`PPMD7_MAX_MEM_SIZE`]
19    pub fn new(reader: R, order: u32, mem_size: u32) -> crate::Result<Self> {
20        if !(PPMD7_MIN_ORDER..=PPMD7_MAX_ORDER).contains(&order)
21            || !(PPMD7_MIN_MEM_SIZE..=PPMD7_MAX_MEM_SIZE).contains(&mem_size)
22        {
23            return Err(Error::InvalidParameter);
24        }
25
26        let ppmd = PPMd7::new_decoder_7a(reader, order, mem_size)?;
27
28        Ok(Self {
29            ppmd,
30            finished: false,
31        })
32    }
33
34    /// Gets a reference to the underlying reader.
35    pub fn get_ref(&self) -> &R {
36        self.ppmd.get_ref()
37    }
38
39    /// Gets a mutable reference to the underlying reader.
40    ///
41    /// Note that mutation of the stream may result in surprising results if
42    /// this decoder is continued to be used.
43    pub fn get_mut(&mut self) -> &mut R {
44        self.ppmd.get_mut()
45    }
46
47    /// Returns the inner reader.
48    pub fn into_inner(self) -> R {
49        self.ppmd.into_inner()
50    }
51}
52
53impl<R: Read> Read for Ppmd7aDecoder<R> {
54    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
55        if self.finished {
56            return Ok(0);
57        }
58
59        if buf.is_empty() {
60            return Ok(0);
61        }
62
63        let mut sym = 0;
64        let mut decoded = 0;
65
66        for byte in buf.iter_mut() {
67            match self.ppmd.decode_symbol() {
68                Ok(symbol) => sym = symbol,
69                Err(err) => {
70                    if err.kind() == std::io::ErrorKind::UnexpectedEof {
71                        self.finished = true;
72                        return Ok(decoded);
73                    }
74                    return Err(err);
75                }
76            }
77
78            if sym < 0 {
79                break;
80            }
81
82            *byte = sym as u8;
83            decoded += 1;
84        }
85
86        let code = self.ppmd.range_decoder_code();
87
88        if sym >= 0 {
89            return Ok(decoded);
90        }
91
92        self.finished = true;
93
94        if sym != SYM_END || code != 0 {
95            return Err(std::io::Error::new(
96                std::io::ErrorKind::InvalidData,
97                "Error during PPMd decoding",
98            ));
99        }
100
101        // END_MARKER detected
102        Ok(decoded)
103    }
104}