brotli/enc/
reader.rs

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