Skip to main content

ppmd_rust/
decoder_8.rs

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