brotli/enc/
reader.rs

1use alloc::{Allocator, SliceWrapperMut};
2#[cfg(feature = "std")]
3use std::io;
4#[cfg(feature = "std")]
5use std::io::{Error, ErrorKind, Read};
6
7#[cfg(feature = "std")]
8pub use alloc_stdlib::StandardAlloc;
9use brotli_decompressor::CustomRead;
10#[cfg(feature = "std")]
11pub use brotli_decompressor::{IntoIoReader, IoReaderWrapper, IoWriterWrapper};
12
13use super::backward_references::BrotliEncoderParams;
14use super::combined_alloc::BrotliAlloc;
15use super::encode::{
16    BrotliEncoderDestroyInstance, BrotliEncoderOperation, BrotliEncoderParameter,
17    BrotliEncoderStateStruct,
18};
19use super::interface;
20use crate::enc::combined_alloc::allocate;
21
22#[cfg(feature = "std")]
23pub struct CompressorReaderCustomAlloc<R: Read, BufferType: SliceWrapperMut<u8>, Alloc: BrotliAlloc>(
24    CompressorReaderCustomIo<io::Error, IntoIoReader<R>, BufferType, Alloc>,
25);
26
27#[cfg(feature = "std")]
28impl<R: Read, BufferType: SliceWrapperMut<u8>, Alloc: BrotliAlloc>
29    CompressorReaderCustomAlloc<R, BufferType, Alloc>
30{
31    pub fn new(r: R, buffer: BufferType, alloc: Alloc, q: u32, lgwin: u32) -> Self {
32        CompressorReaderCustomAlloc::<R, BufferType, Alloc>(CompressorReaderCustomIo::<
33            Error,
34            IntoIoReader<R>,
35            BufferType,
36            Alloc,
37        >::new(
38            IntoIoReader::<R>(r),
39            buffer,
40            alloc,
41            Error::new(ErrorKind::InvalidData, "Invalid Data"),
42            q,
43            lgwin,
44        ))
45    }
46
47    pub fn get_ref(&self) -> &R {
48        &self.0.get_ref().0
49    }
50    pub fn into_inner(self) -> R {
51        self.0.into_inner().0
52    }
53}
54
55#[cfg(feature = "std")]
56impl<R: Read, BufferType: SliceWrapperMut<u8>, Alloc: BrotliAlloc> Read
57    for CompressorReaderCustomAlloc<R, BufferType, Alloc>
58{
59    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
60        self.0.read(buf)
61    }
62}
63
64#[cfg(feature = "std")]
65pub struct CompressorReader<R: Read>(
66    CompressorReaderCustomAlloc<
67        R,
68        <StandardAlloc as Allocator<u8>>::AllocatedMemory,
69        StandardAlloc,
70    >,
71);
72
73#[cfg(feature = "std")]
74impl<R: Read> CompressorReader<R> {
75    pub fn new(r: R, buffer_size: usize, q: u32, lgwin: u32) -> Self {
76        let mut alloc = StandardAlloc::default();
77        let buffer = allocate::<u8, _>(
78            &mut alloc,
79            if buffer_size == 0 { 4096 } else { buffer_size },
80        );
81        CompressorReader::<R>(CompressorReaderCustomAlloc::new(r, buffer, alloc, q, lgwin))
82    }
83
84    pub fn with_params(r: R, buffer_size: usize, params: &BrotliEncoderParams) -> Self {
85        let mut reader = Self::new(r, buffer_size, params.quality as u32, params.lgwin as u32);
86        (reader.0).0.state.0.params = params.clone();
87        reader
88    }
89
90    pub fn get_ref(&self) -> &R {
91        self.0.get_ref()
92    }
93    pub fn into_inner(self) -> R {
94        self.0.into_inner()
95    }
96}
97
98#[cfg(feature = "std")]
99impl<R: Read> Read for CompressorReader<R> {
100    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
101        self.0.read(buf)
102    }
103}
104
105pub struct CompressorReaderCustomIo<
106    ErrType,
107    R: CustomRead<ErrType>,
108    BufferType: SliceWrapperMut<u8>,
109    Alloc: BrotliAlloc,
110> {
111    input_buffer: BufferType,
112    total_out: Option<usize>,
113    input_offset: usize,
114    input_len: usize,
115    input: R,
116    input_eof: bool,
117    error_if_invalid_data: Option<ErrType>,
118    state: StateWrapper<Alloc>,
119}
120struct StateWrapper<Alloc: BrotliAlloc>(BrotliEncoderStateStruct<Alloc>);
121
122impl<Alloc: BrotliAlloc> Drop for StateWrapper<Alloc> {
123    fn drop(&mut self) {
124        BrotliEncoderDestroyInstance(&mut self.0);
125    }
126}
127
128impl<ErrType, R: CustomRead<ErrType>, BufferType: SliceWrapperMut<u8>, Alloc: BrotliAlloc>
129    CompressorReaderCustomIo<ErrType, R, BufferType, Alloc>
130{
131    pub fn new(
132        r: R,
133        buffer: BufferType,
134        alloc: Alloc,
135        invalid_data_error_type: ErrType,
136        q: u32,
137        lgwin: u32,
138    ) -> Self {
139        let mut ret = CompressorReaderCustomIo {
140            input_buffer: buffer,
141            total_out: Some(0),
142            input_offset: 0,
143            input_len: 0,
144            input_eof: false,
145            input: r,
146            state: StateWrapper(BrotliEncoderStateStruct::new(alloc)),
147            error_if_invalid_data: Some(invalid_data_error_type),
148        };
149        ret.state
150            .0
151            .set_parameter(BrotliEncoderParameter::BROTLI_PARAM_QUALITY, q);
152        ret.state
153            .0
154            .set_parameter(BrotliEncoderParameter::BROTLI_PARAM_LGWIN, lgwin);
155
156        ret
157    }
158    pub fn copy_to_front(&mut self) {
159        let avail_in = self.input_len - self.input_offset;
160        if self.input_offset == self.input_buffer.slice_mut().len() {
161            self.input_offset = 0;
162            self.input_len = 0;
163        } else if self.input_offset + 256 > self.input_buffer.slice_mut().len()
164            && avail_in < self.input_offset
165        {
166            let (first, second) = self
167                .input_buffer
168                .slice_mut()
169                .split_at_mut(self.input_offset);
170            first[0..avail_in].clone_from_slice(&second[0..avail_in]);
171            self.input_len -= self.input_offset;
172            self.input_offset = 0;
173        }
174    }
175    pub fn into_inner(self) -> R {
176        match self {
177            CompressorReaderCustomIo {
178                input_buffer: _ib,
179                total_out: _to,
180                input_offset: _io,
181                input_len: _len,
182                input,
183                input_eof: _ieof,
184                error_if_invalid_data: _eiid,
185                state: _state,
186            } => input,
187        }
188    }
189    pub fn get_ref(&self) -> &R {
190        &self.input
191    }
192}
193impl<ErrType, R: CustomRead<ErrType>, BufferType: SliceWrapperMut<u8>, Alloc: BrotliAlloc>
194    CustomRead<ErrType> for CompressorReaderCustomIo<ErrType, R, BufferType, Alloc>
195{
196    fn read(&mut self, buf: &mut [u8]) -> Result<usize, ErrType> {
197        let mut nop_callback =
198            |_data: &mut interface::PredictionModeContextMap<interface::InputReferenceMut>,
199             _cmds: &mut [interface::StaticCommand],
200             _mb: interface::InputPair,
201             _mfv: &mut Alloc| ();
202        let mut output_offset: usize = 0;
203        let mut avail_out = buf.len();
204        let mut avail_in = self.input_len - self.input_offset;
205        while output_offset == 0 {
206            if self.input_len < self.input_buffer.slice_mut().len() && !self.input_eof {
207                match self
208                    .input
209                    .read(&mut self.input_buffer.slice_mut()[self.input_len..])
210                {
211                    Err(e) => return Err(e),
212                    Ok(size) => {
213                        if size == 0 {
214                            self.input_eof = true;
215                        } else {
216                            self.input_len += size;
217                            avail_in = self.input_len - self.input_offset;
218                        }
219                    }
220                }
221            }
222            let op: BrotliEncoderOperation;
223            if avail_in == 0 {
224                op = BrotliEncoderOperation::BROTLI_OPERATION_FINISH;
225            } else {
226                op = BrotliEncoderOperation::BROTLI_OPERATION_PROCESS;
227            }
228            let ret = self.state.0.compress_stream(
229                op,
230                &mut avail_in,
231                self.input_buffer.slice_mut(),
232                &mut self.input_offset,
233                &mut avail_out,
234                buf,
235                &mut output_offset,
236                &mut self.total_out,
237                &mut nop_callback,
238            );
239            if avail_in == 0 {
240                self.copy_to_front();
241            }
242            if !ret {
243                return Err(self.error_if_invalid_data.take().unwrap());
244            }
245            if self.state.0.is_finished() {
246                break;
247            }
248        }
249        Ok(output_offset)
250    }
251}