use thiserror::Error;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Error)]
#[non_exhaustive]
pub enum DecodeConfigError {
#[error("standard window limit must be 10..=24 bits, got {max_bits}")]
StandardWindow {
max_bits: u8,
},
#[error("large window limit must be 10..=62 bits, got {max_bits}")]
LargeWindow {
max_bits: u8,
},
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Error)]
#[non_exhaustive]
pub enum InvalidDataKind {
#[error("stream header")]
Header,
#[error("meta-block")]
MetaBlock,
#[error("Huffman code")]
Huffman,
#[error("context map")]
ContextMap,
#[error("distance")]
Distance,
#[error("dictionary reference")]
DictionaryReference,
#[error("padding")]
Padding,
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum DecodeError {
#[error("invalid Brotli {kind}")]
InvalidData {
kind: InvalidDataKind,
},
#[error("unexpected end of compressed input")]
UnexpectedEndOfInput,
#[error("trailing compressed data at byte {offset}")]
TrailingData {
offset: u64,
},
#[error("output slice is full after {written} bytes")]
OutputTooSmall {
written: usize,
},
#[error("expected {expected} output bytes, decoded {actual}")]
OutputSizeMismatch {
expected: u64,
actual: u64,
},
#[error("compressed input exceeds {limit} bytes")]
InputLimitExceeded {
limit: u64,
},
#[error("decoded output exceeds {limit} bytes")]
OutputLimitExceeded {
limit: u64,
},
#[error("declared {declared}-bit window exceeds allowed {allowed} bits")]
WindowLimitExceeded {
declared: u8,
allowed: u8,
},
#[error("large window headers are disabled")]
LargeWindowDisabled,
#[error("decoder workspace exceeds {limit} bytes")]
MemoryLimitExceeded {
limit: usize,
},
#[error("decoder allocation failed")]
AllocationFailed,
#[error("decoder size overflow")]
SizeOverflow,
#[error("decoder has an abandoned session")]
AbandonedSession,
#[error("invalid decoder state")]
InvalidState,
#[error("decoder internal invariant failed")]
InternalInvariant,
}
impl From<InvalidDataKind> for DecodeError {
fn from(kind: InvalidDataKind) -> Self {
Self::InvalidData { kind }
}
}
#[cfg(not(feature = "no_std"))]
impl From<DecodeError> for std::io::Error {
fn from(error: DecodeError) -> Self {
use std::io::ErrorKind;
let kind = match &error {
DecodeError::InvalidData { .. }
| DecodeError::TrailingData { .. }
| DecodeError::OutputSizeMismatch { .. } => ErrorKind::InvalidData,
DecodeError::UnexpectedEndOfInput => ErrorKind::UnexpectedEof,
DecodeError::InvalidState
| DecodeError::AbandonedSession
| DecodeError::OutputTooSmall { .. } => ErrorKind::InvalidInput,
DecodeError::AllocationFailed => ErrorKind::OutOfMemory,
_ => ErrorKind::Other,
};
Self::new(kind, error)
}
}