ppmd_rust/
decoder_7.rs

1use crate::Error;
2use crate::byte_reader::ByteReader;
3use crate::memory::Memory;
4use ppmd_sys::{
5    CPpmd7, PPMD7_MAX_MEM_SIZE, PPMD7_MAX_ORDER, PPMD7_MIN_MEM_SIZE, PPMD7_MIN_ORDER,
6    PPMD7_SYM_END, Ppmd7_Alloc, Ppmd7_Construct, Ppmd7_Free, Ppmd7_Init, Ppmd7z_DecodeSymbol,
7    Ppmd7z_RangeDec_Init,
8};
9use std::io::Read;
10
11/// A decoder to decode PPMd7 (PPMdH) with the 7z range coder.
12pub struct Ppmd7Decoder<R: Read> {
13    ppmd: CPpmd7,
14    _reader: ByteReader<R>,
15    memory: Memory,
16    finished: bool,
17}
18
19impl<R: Read> Ppmd7Decoder<R> {
20    /// Creates a new [`Ppmd7Decoder`].
21    pub fn new(reader: R, order: u32, mem_size: u32) -> crate::Result<Self> {
22        if !(PPMD7_MIN_ORDER..=PPMD7_MAX_ORDER).contains(&order)
23            || !(PPMD7_MIN_MEM_SIZE..=PPMD7_MAX_MEM_SIZE).contains(&mem_size)
24        {
25            return Err(Error::InvalidParameter);
26        }
27
28        let mut ppmd = unsafe { std::mem::zeroed::<CPpmd7>() };
29        unsafe { Ppmd7_Construct(&mut ppmd) };
30
31        let mut memory = Memory::new(mem_size);
32
33        let success = unsafe { Ppmd7_Alloc(&mut ppmd, mem_size, memory.allocation()) };
34
35        if success == 0 {
36            return Err(Error::InternalError("Failed to allocate memory"));
37        }
38
39        let mut reader = ByteReader::new(reader);
40        let range_decoder = unsafe { &mut ppmd.rc.dec };
41        range_decoder.Stream = reader.byte_in_ptr();
42
43        let success = unsafe { Ppmd7z_RangeDec_Init(&mut ppmd.rc.dec) };
44
45        if success == 0 {
46            return Err(Error::InternalError("Failed to initialize range decoder"));
47        }
48
49        unsafe { Ppmd7_Init(&mut ppmd, order) };
50
51        Ok(Self {
52            ppmd,
53            _reader: reader,
54            memory,
55            finished: false,
56        })
57    }
58}
59
60impl<R: Read> Drop for Ppmd7Decoder<R> {
61    fn drop(&mut self) {
62        unsafe { Ppmd7_Free(&mut self.ppmd, self.memory.allocation()) }
63    }
64}
65
66impl<R: Read> Read for Ppmd7Decoder<R> {
67    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
68        if self.finished {
69            return Ok(0);
70        }
71
72        if buf.is_empty() {
73            return Ok(0);
74        }
75
76        let mut sym = 0;
77        let mut decoded = 0;
78
79        unsafe {
80            for byte in buf.iter_mut() {
81                sym = Ppmd7z_DecodeSymbol(&mut self.ppmd);
82
83                if sym < 0 {
84                    break;
85                }
86
87                *byte = sym as u8;
88                decoded += 1;
89            }
90        }
91
92        let code = unsafe { self.ppmd.rc.dec.Code };
93
94        if sym >= 0 && (!self.finished || decoded != buf.len() || code == 0) {
95            return Ok(decoded);
96        }
97
98        self.finished = true;
99
100        if sym != PPMD7_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        Ok(decoded)
108    }
109}
110
111#[cfg(test)]
112mod test {
113    use super::Ppmd7Decoder;
114
115    const ORDER: u32 = 8;
116    const MEM_SIZE: u32 = 262144;
117
118    #[test]
119    fn ppmd7decoder_init_drop() {
120        let reader: &[u8] = &[];
121        let decoder = Ppmd7Decoder::new(reader, ORDER, MEM_SIZE).unwrap();
122        assert!(!decoder.ppmd.Base.is_null());
123    }
124}