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}