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}