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}