1use std::error::Error;
10use std::ffi::CStr;
11use std::io::{BufRead, Read, Write};
12use std::{fmt, io, ptr, slice};
13
14use brotlic_sys::*;
15
16use crate::{IntoInnerError, SetParameterError};
17
18pub struct BrotliDecoder {
25 state: *mut BrotliDecoderState,
26}
27
28unsafe impl Send for BrotliDecoder {}
29unsafe impl Sync for BrotliDecoder {}
30
31impl BrotliDecoder {
32 #[doc(alias = "BrotliDecoderCreateInstance")]
38 pub fn new() -> Self {
39 let instance = unsafe { BrotliDecoderCreateInstance(None, None, ptr::null_mut()) };
40
41 if !instance.is_null() {
42 BrotliDecoder { state: instance }
43 } else {
44 panic!("BrotliDecoderCreateInstance returned NULL: failed to allocate or initialize");
45 }
46 }
47
48 #[doc(alias = "BrotliDecoderIsFinished")]
50 pub fn is_finished(&self) -> bool {
51 unsafe { BrotliDecoderIsFinished(self.state) != 0 }
52 }
53
54 #[doc(alias = "BrotliDecoderDecompressStream")]
72 pub fn decompress(
73 &mut self,
74 input: &[u8],
75 output: &mut [u8],
76 ) -> Result<DecodeResult, DecodeError> {
77 let mut input_ptr = input.as_ptr();
78 let mut input_len = input.len();
79 let mut output_ptr = output.as_mut_ptr();
80 let mut output_len = output.len();
81
82 let result = unsafe {
83 BrotliDecoderDecompressStream(
84 self.state,
85 &mut input_len,
86 &mut input_ptr,
87 &mut output_len,
88 &mut output_ptr,
89 ptr::null_mut(),
90 )
91 };
92
93 let bytes_read = input.len() - input_len;
94 let bytes_written = output.len() - output_len;
95
96 #[allow(non_upper_case_globals)]
97 let info = match result {
98 BrotliDecoderResult_BROTLI_DECODER_RESULT_ERROR => return Err(self.last_error()),
99 BrotliDecoderResult_BROTLI_DECODER_RESULT_SUCCESS => DecoderInfo::Finished,
100 BrotliDecoderResult_BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT => {
101 DecoderInfo::NeedsMoreInput
102 }
103 BrotliDecoderResult_BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT => {
104 DecoderInfo::NeedsMoreOutput
105 }
106 _ => panic!("BrotliDecoderDecompressStream returned an unknown error code"),
107 };
108
109 Ok(DecodeResult {
110 bytes_read,
111 bytes_written,
112 info,
113 })
114 }
115
116 pub fn give_input(&mut self, input: &[u8]) -> Result<(usize, DecoderInfo), DecodeError> {
119 let res = self.decompress(input, &mut [])?;
120
121 Ok((res.bytes_read, res.info))
122 }
123
124 #[doc(alias = "BrotliDecoderHasMoreOutput")]
126 pub fn has_output(&self) -> bool {
127 unsafe { BrotliDecoderHasMoreOutput(self.state) != 0 }
128 }
129
130 #[doc(alias = "BrotliDecoderTakeOutput")]
142 pub unsafe fn take_output(&mut self) -> Option<&[u8]> {
143 if self.has_output() {
144 let mut len: usize = 0;
145 let output = BrotliDecoderTakeOutput(self.state, &mut len as _);
146
147 Some(slice::from_raw_parts(output, len))
148 } else {
149 None
150 }
151 }
152
153 #[doc(alias = "BrotliDecoderVersion")]
155 pub fn version() -> u32 {
156 unsafe { BrotliDecoderVersion() }
157 }
158
159 fn set_param(
160 &mut self,
161 param: BrotliDecoderParameter,
162 value: u32,
163 ) -> Result<(), SetParameterError> {
164 let r = unsafe { BrotliDecoderSetParameter(self.state, param, value) };
165
166 if r != 0 {
167 Ok(())
168 } else {
169 Err(SetParameterError::Generic)
170 }
171 }
172
173 fn last_error(&self) -> DecodeError {
174 let ec = unsafe { BrotliDecoderGetErrorCode(self.state) };
175
176 #[allow(non_upper_case_globals)]
177 match ec {
178 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE => {
179 DecodeError::FormatExuberantNibble
180 }
181 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_RESERVED => {
182 DecodeError::FormatReserved
183 }
184 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE => {
185 DecodeError::FormatExuberantMetaNibble
186 }
187 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET => {
188 DecodeError::FormatSimpleHuffmanAlphabet
189 }
190 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME => {
191 DecodeError::FormatSimpleHuffmanSame
192 }
193 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_CL_SPACE => {
194 DecodeError::FormatClSpace
195 }
196 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE => {
197 DecodeError::FormatHuffmanSpace
198 }
199 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT => {
200 DecodeError::FormatContextMapRepeat
201 }
202 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1 => {
203 DecodeError::FormatBlockLength1
204 }
205 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2 => {
206 DecodeError::FormatBlockLength2
207 }
208 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_TRANSFORM => {
209 DecodeError::FormatTransform
210 }
211 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_DICTIONARY => {
212 DecodeError::FormatDictionary
213 }
214 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS => {
215 DecodeError::FormatWindowBits
216 }
217 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_PADDING_1 => {
218 DecodeError::FormatPadding1
219 }
220 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_PADDING_2 => {
221 DecodeError::FormatPadding2
222 }
223 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_DISTANCE => {
224 DecodeError::FormatDistance
225 }
226 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY => {
227 DecodeError::CompoundDictionary
228 }
229 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET => {
230 DecodeError::DictionaryNotSet
231 }
232 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_INVALID_ARGUMENTS => {
233 DecodeError::InvalidArguments
234 }
235 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES => {
236 DecodeError::AllocContextModes
237 }
238 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS => {
239 DecodeError::AllocTreeGroups
240 }
241 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP => {
242 DecodeError::AllocContextMap
243 }
244 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1 => {
245 DecodeError::AllocRingBuffer1
246 }
247 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2 => {
248 DecodeError::AllocRingBuffer2
249 }
250 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES => {
251 DecodeError::AllocBlockTypeTrees
252 }
253 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_UNREACHABLE => DecodeError::Unreachable,
254 _ => DecodeError::UnknownError,
255 }
256 }
257}
258
259impl fmt::Debug for BrotliDecoder {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 f.debug_struct("BrotliDecoder")
262 .field("state", &self.state)
263 .finish_non_exhaustive()
264 }
265}
266
267impl Default for BrotliDecoder {
268 fn default() -> Self {
269 BrotliDecoder::new()
270 }
271}
272
273impl Drop for BrotliDecoder {
274 fn drop(&mut self) {
275 unsafe {
276 BrotliDecoderDestroyInstance(self.state);
277 }
278 }
279}
280
281#[derive(Debug, Clone)]
292pub struct BrotliDecoderOptions {
293 disable_ring_buffer_reallocation: Option<bool>,
294 large_window_size: Option<bool>,
295}
296
297impl BrotliDecoderOptions {
298 pub fn new() -> Self {
303 BrotliDecoderOptions {
304 disable_ring_buffer_reallocation: None,
305 large_window_size: None,
306 }
307 }
308
309 pub fn disable_ring_buffer_reallocation(
314 &mut self,
315 disable_ring_buffer_reallocation: bool,
316 ) -> &mut Self {
317 self.disable_ring_buffer_reallocation = Some(disable_ring_buffer_reallocation);
318 self
319 }
320
321 pub fn large_window_size(&mut self, large_window_size: bool) -> &mut Self {
329 self.large_window_size = Some(large_window_size);
330 self
331 }
332
333 #[doc(alias = "BrotliDecoderSetParameter")]
340 pub fn build(&self) -> Result<BrotliDecoder, SetParameterError> {
341 let mut decoder = BrotliDecoder::new();
342
343 self.configure(&mut decoder)?;
344
345 Ok(decoder)
346 }
347
348 fn configure(&self, decoder: &mut BrotliDecoder) -> Result<(), SetParameterError> {
349 if let Some(disable_ring_buffer_reallocation) = self.disable_ring_buffer_reallocation {
350 let key = BrotliDecoderParameter_BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION;
351 let value = disable_ring_buffer_reallocation as u32;
352
353 decoder.set_param(key, value)?;
354 }
355
356 if let Some(large_window_size) = self.large_window_size {
357 let key = BrotliDecoderParameter_BROTLI_DECODER_PARAM_LARGE_WINDOW;
358 let value = large_window_size as u32;
359
360 decoder.set_param(key, value)?;
361 }
362
363 Ok(())
364 }
365}
366
367impl Default for BrotliDecoderOptions {
368 fn default() -> Self {
369 BrotliDecoderOptions::new()
370 }
371}
372
373#[derive(Debug, Copy, Clone, Eq, PartialEq)]
375pub struct DecodeResult {
376 pub bytes_read: usize,
378 pub bytes_written: usize,
380 pub info: DecoderInfo,
383}
384
385#[derive(Debug, Copy, Clone, Eq, PartialEq)]
388pub enum DecoderInfo {
389 Finished,
391 NeedsMoreInput,
393 NeedsMoreOutput,
395}
396
397#[derive(Debug, Copy, Clone, Eq, PartialEq)]
399#[non_exhaustive]
400#[allow(missing_docs)]
401pub enum DecodeError {
402 UnknownError = 0,
403 FormatExuberantNibble =
404 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE as isize,
405 FormatReserved = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_RESERVED as isize,
406 FormatExuberantMetaNibble =
407 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE as isize,
408 FormatSimpleHuffmanAlphabet =
409 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET as isize,
410 FormatSimpleHuffmanSame =
411 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME as isize,
412 FormatClSpace = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_CL_SPACE as isize,
413 FormatHuffmanSpace = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE as isize,
414 FormatContextMapRepeat =
415 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT as isize,
416 FormatBlockLength1 = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1 as isize,
417 FormatBlockLength2 = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2 as isize,
418 FormatTransform = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_TRANSFORM as isize,
419 FormatDictionary = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_DICTIONARY as isize,
420 FormatWindowBits = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS as isize,
421 FormatPadding1 = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_PADDING_1 as isize,
422 FormatPadding2 = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_PADDING_2 as isize,
423 FormatDistance = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_FORMAT_DISTANCE as isize,
424 CompoundDictionary = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY as isize,
425 DictionaryNotSet = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET as isize,
426 InvalidArguments = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_INVALID_ARGUMENTS as isize,
427 AllocContextModes = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES as isize,
428 AllocTreeGroups = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS as isize,
429 AllocContextMap = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP as isize,
430 AllocRingBuffer1 = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1 as isize,
431 AllocRingBuffer2 = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2 as isize,
432 AllocBlockTypeTrees =
433 BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES as isize,
434 Unreachable = BrotliDecoderErrorCode_BROTLI_DECODER_ERROR_UNREACHABLE as isize,
435}
436
437impl Error for DecodeError {}
438
439impl fmt::Display for DecodeError {
440 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441 if *self == DecodeError::UnknownError {
442 write!(f, "decode error: unknown error")
443 } else {
444 let str = unsafe {
445 let error_code = *self as BrotliDecoderErrorCode;
446 let error_string = BrotliDecoderErrorString(error_code);
447 let c_str = CStr::from_ptr(error_string);
448 c_str
449 .to_str()
450 .expect("invalid utf-8 returned from BrotliDecoderErrorString")
451 };
452
453 write!(f, "brotli decoder error: {}", str)
454 }
455 }
456}
457
458impl From<DecodeError> for io::Error {
459 fn from(err: DecodeError) -> Self {
460 io::Error::new(io::ErrorKind::Other, err)
461 }
462}
463
464#[derive(Debug)]
487pub struct DecompressorReader<R: BufRead> {
488 inner: R,
489 decoder: BrotliDecoder,
490}
491
492impl<R: BufRead> DecompressorReader<R> {
493 pub fn new(inner: R) -> Self {
499 DecompressorReader {
500 inner,
501 decoder: BrotliDecoder::new(),
502 }
503 }
504
505 pub fn with_decoder(decoder: BrotliDecoder, inner: R) -> Self {
523 DecompressorReader { inner, decoder }
524 }
525
526 pub fn get_ref(&self) -> &R {
528 &self.inner
529 }
530
531 pub fn get_mut(&mut self) -> &mut R {
535 &mut self.inner
536 }
537
538 pub fn into_inner(self) -> Result<R, IntoInnerError<DecompressorReader<R>>> {
545 if self.decoder.is_finished() {
546 Ok(self.inner)
547 } else {
548 Err(IntoInnerError::new(
549 self,
550 io::ErrorKind::UnexpectedEof.into(),
551 ))
552 }
553 }
554
555 pub fn into_parts(self) -> (R, BrotliDecoder) {
561 (self.inner, self.decoder)
562 }
563}
564
565impl<R: BufRead> Read for DecompressorReader<R> {
566 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
567 loop {
568 let input = self.inner.fill_buf()?;
569 let eof = input.is_empty();
570 let DecodeResult {
571 bytes_read,
572 bytes_written,
573 info,
574 } = self.decoder.decompress(input, buf)?;
575 self.inner.consume(bytes_read);
576
577 match info {
578 _ if bytes_written > 0 => return Ok(bytes_written),
579 DecoderInfo::Finished => return Ok(0),
580 DecoderInfo::NeedsMoreInput if eof => {
581 return Err(io::ErrorKind::UnexpectedEof.into());
582 }
583 DecoderInfo::NeedsMoreInput => continue,
584 DecoderInfo::NeedsMoreOutput if buf.is_empty() => return Ok(0),
585 DecoderInfo::NeedsMoreOutput => panic!(
586 "decoder needs output despite not giving any while having the chance to do so"
587 ),
588 };
589 }
590 }
591}
592
593#[derive(Debug)]
619pub struct DecompressorWriter<W: Write> {
620 inner: W,
621 decoder: BrotliDecoder,
622 panicked: bool,
623}
624
625impl<W: Write> DecompressorWriter<W> {
626 pub fn new(inner: W) -> DecompressorWriter<W> {
632 DecompressorWriter {
633 inner,
634 decoder: BrotliDecoder::new(),
635 panicked: false,
636 }
637 }
638
639 pub fn with_decoder(decoder: BrotliDecoder, inner: W) -> Self {
656 DecompressorWriter {
657 inner,
658 decoder,
659 panicked: false,
660 }
661 }
662
663 pub fn get_ref(&self) -> &W {
665 &self.inner
666 }
667
668 pub fn get_mut(&mut self) -> &mut W {
672 &mut self.inner
673 }
674
675 pub fn into_inner(self) -> Result<W, IntoInnerError<DecompressorWriter<W>>> {
687 if self.decoder.is_finished() {
688 Ok(self.into_parts().0)
689 } else {
690 Err(IntoInnerError::new(
691 self,
692 io::ErrorKind::UnexpectedEof.into(),
693 ))
694 }
695 }
696
697 pub fn into_parts(self) -> (W, Result<BrotliDecoder, WriterPanicked>) {
707 let inner = self.inner;
708 let decoder = self.decoder;
709
710 let decoder = if !self.panicked {
711 Ok(decoder)
712 } else {
713 Err(WriterPanicked { decoder })
714 };
715
716 (inner, decoder)
717 }
718
719 fn flush_decoder_output(&mut self) -> io::Result<()> {
720 while let Some(output) = unsafe { self.decoder.take_output() } {
721 self.panicked = true;
722 let r = self.inner.write_all(output);
723 self.panicked = false;
724 r?;
725 }
726
727 Ok(())
728 }
729}
730
731impl<W: Write> Write for DecompressorWriter<W> {
732 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
733 let (bytes_read, _decoder_result) = self.decoder.give_input(buf)?;
734 self.flush_decoder_output()?;
735
736 Ok(bytes_read)
737 }
738
739 fn flush(&mut self) -> io::Result<()> {
740 self.inner.flush()
741 }
742}
743
744#[derive(Debug)]
748pub struct WriterPanicked {
749 decoder: BrotliDecoder,
750}
751
752impl WriterPanicked {
753 pub fn into_inner(self) -> BrotliDecoder {
757 self.decoder
758 }
759}
760
761impl Error for WriterPanicked {}
762
763impl fmt::Display for WriterPanicked {
764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
765 f.write_str(
766 "DecompressorWriter inner writer panicked, what data remains unwritten is not known",
767 )
768 }
769}