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