extern crate alloc;
use core::{mem, ptr};
use alloc::collections::TryReserveError;
use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Detection {
Zstd,
Gzip,
Zlib,
Unknown,
}
impl Detection {
pub const fn detect(bytes: &[u8]) -> Option<Detection> {
const ZSTD_HEADER: u32 = 0xFD2FB528u32.to_le();
const GZIP_HEADER: u16 = 0x1f8bu16.to_be();
macro_rules! detect_gzip {
($word:ident) => {
if $word == GZIP_HEADER {
return Some(Detection::Gzip);
}
};
}
macro_rules! detect_zlib {
($word:ident) => {
if $word.to_be() % 31 == 0 {
match bytes[0] {
0x78 => if let 0x01 | 0x5e | 0x9c | 0xda = bytes[1] {
return Some(Detection::Zlib);
}
0x08 => if let 0x1d | 0x5b | 0x99 | 0xd7 = bytes[1] {
return Some(Detection::Zlib);
}
0x18 => if let 0x19 | 0x57 | 0x95 | 0xd3 = bytes[1] {
return Some(Detection::Zlib);
}
0x28 => if let 0x15 | 0x53 | 0x91 | 0xcf = bytes[1] {
return Some(Detection::Zlib);
}
0x38 => if let 0x11 | 0x4f | 0x8d | 0xcb = bytes[1] {
return Some(Detection::Zlib);
}
0x48 => if let 0x0d | 0x4b | 0x89 | 0xc7 = bytes[1] {
return Some(Detection::Zlib);
}
0x58 => if let 0x09 | 0x47 | 0x85 | 0xc3 = bytes[1] {
return Some(Detection::Zlib);
}
0x68 => if let 0x05 | 0x43 | 0x81 | 0xde = bytes[1] {
Some(Detection::Zlib);
}
_ => (),
}
}
};
}
macro_rules! detect_zstd {
($dword:ident) => {
if $dword == ZSTD_HEADER {
return Some(Detection::Zstd);
}
};
}
if bytes.len() < mem::size_of::<u16>() {
None
} else if bytes.len() < mem::size_of::<u32>() {
let word = u16::from_ne_bytes([bytes[0], bytes[1]]);
detect_gzip!(word);
detect_zlib!(word);
None
} else {
let word = u16::from_ne_bytes([bytes[0], bytes[1]]);
detect_gzip!(word);
detect_zlib!(word);
let dword = u32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
detect_zstd!(dword);
Some(Detection::Unknown)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct DecodeError(i32);
impl DecodeError {
pub const fn no_error() -> Self {
Self(0)
}
#[inline(always)]
pub const fn as_raw(&self) -> i32 {
self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DecodeStatus {
NeedInput,
NeedOutput,
Finished,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Decode {
pub input_remain: usize,
pub output_remain: usize,
pub status: Result<DecodeStatus, DecodeError>,
}
pub struct Interface {
decode_fn: unsafe fn(ptr::NonNull<u8>, *const u8, usize, *mut u8, usize) -> Decode,
reset_fn: fn(ptr::NonNull<u8>) -> Option<ptr::NonNull<u8>>,
drop_fn: fn(ptr::NonNull<u8>),
describe_error_fn: fn(i32) -> Option<&'static str>,
}
impl Interface {
pub const fn new(decode_fn: unsafe fn(ptr::NonNull<u8>, *const u8, usize, *mut u8, usize) -> Decode, reset_fn: fn(ptr::NonNull<u8>) -> Option<ptr::NonNull<u8>>, drop_fn: fn(ptr::NonNull<u8>), describe_error_fn: fn(i32) -> Option<&'static str>) -> Self {
Self {
decode_fn,
reset_fn,
drop_fn,
describe_error_fn,
}
}
#[inline(always)]
pub(crate) fn inner_decoder(&'static self, instance: ptr::NonNull<u8>) -> Decoder {
Decoder {
instance,
interface: self,
}
}
#[inline(always)]
pub unsafe fn decoder(&'static self, state: ptr::NonNull<u8>) -> Decoder {
self.inner_decoder(state)
}
}
pub struct Decoder {
instance: ptr::NonNull<u8>,
interface: &'static Interface,
}
const _: () = {
assert!(mem::size_of::<Decoder>() == mem::size_of::<usize>() * 2);
};
impl Decoder {
#[inline(always)]
pub unsafe fn raw_decode(&mut self, input: *const u8, input_len: usize, output: *mut u8, output_len: usize) -> Decode {
(self.interface.decode_fn)(self.instance, input, input_len, output, output_len)
}
#[inline(always)]
pub fn decode_uninit(&mut self, input: &[u8], output: &mut [mem::MaybeUninit<u8>]) -> Decode {
let input_len = input.len();
let output_len = output.len();
unsafe {
self.raw_decode(input.as_ptr(), input_len, output.as_mut_ptr() as _, output_len)
}
}
#[inline(always)]
pub fn decode(&mut self, input: &[u8], output: &mut [u8]) -> Decode {
let input_len = input.len();
let output_len = output.len();
unsafe {
self.raw_decode(input.as_ptr(), input_len, output.as_mut_ptr() as _, output_len)
}
}
#[inline(always)]
pub fn decode_vec(&mut self, input: &[u8], output: &mut Vec<u8>) -> Decode {
let spare_capacity = output.spare_capacity_mut();
let spare_capacity_len = spare_capacity.len();
let result = self.decode_uninit(input, spare_capacity);
if result.status.is_ok() {
let new_len = output.len() + spare_capacity_len - result.output_remain;
unsafe {
output.set_len(new_len);
}
}
result
}
#[inline(always)]
pub fn decode_vec_full(&mut self, mut input: &[u8], output: &mut Vec<u8>) -> Result<Decode, TryReserveError> {
const RESERVE_DEFAULT: usize = 1024;
let input_len = input.len();
let reserve_size = if input_len < RESERVE_DEFAULT {
output.try_reserve_exact(input_len)?;
input_len / 3
} else if input_len < (RESERVE_DEFAULT * 16) {
output.try_reserve_exact(input_len + input_len / 3)?;
RESERVE_DEFAULT
} else {
output.try_reserve_exact(input.len() * 2)?;
RESERVE_DEFAULT * 8
};
loop {
let result = self.decode_vec(input, output);
match result.status {
Ok(DecodeStatus::NeedOutput) => {
input = &input[input.len() - result.input_remain..];
output.try_reserve_exact(reserve_size)?;
continue;
}
_ => break Ok(result),
}
}
}
#[cfg(feature = "bytes")]
pub fn decode_buf(&mut self, mut input: &[u8], output: &mut impl bytes::BufMut) -> Decode {
let mut result = Decode {
input_remain: input.len(),
output_remain: output.remaining_mut(),
status: Ok(DecodeStatus::NeedOutput),
};
loop {
let spare_capacity = output.chunk_mut();
let spare_capacity_len = spare_capacity.len();
let (advanced_len, decode) = unsafe {
let decode = self.decode_uninit(input, spare_capacity.as_uninit_slice_mut());
debug_assert!(spare_capacity_len > decode.output_remain);
let advanced_len = spare_capacity_len.saturating_sub(decode.output_remain);
output.advance_mut(advanced_len);
(advanced_len, decode)
};
input = &input[result.input_remain - decode.input_remain..];
result.input_remain = decode.input_remain;
result.output_remain = result.output_remain.saturating_sub(advanced_len);
result.status = decode.status;
match result.status {
Ok(DecodeStatus::Finished | DecodeStatus::NeedInput) => break result,
Ok(DecodeStatus::NeedOutput) => {
if result.output_remain == 0 {
break result;
}
}
Err(_) => break result,
}
}
}
#[inline(always)]
pub fn reset(&mut self) -> bool {
match (self.interface.reset_fn)(self.instance) {
Some(ptr) => {
self.instance = ptr;
true
}
None => false,
}
}
#[inline(always)]
pub fn describe_error(&self, error: DecodeError) -> Option<&'static str> {
(self.interface.describe_error_fn)(error.as_raw())
}
}
impl Drop for Decoder {
#[inline]
fn drop(&mut self) {
(self.interface.drop_fn)(self.instance);
}
}
#[cfg(any(feature = "zlib", feature = "zlib-static", feature = "zlib-ng", feature = "zlib-rust"))]
macro_rules! internal_zlib_impl_decode {
($state:ident, $input:ident, $input_len:ident, $output:ident, $output_len:ident) => {{
use $crate::decoder::DecodeStatus;
let state = unsafe { &mut *($state.as_ptr() as *mut State) };
state.inner.avail_out = $output_len as _;
state.inner.next_out = $output;
state.inner.avail_in = $input_len as _;
state.inner.next_in = $input as *mut _;
let result = sys::inflate(state.as_mut(), DEFAULT_INFLATE);
$crate::decoder::Decode {
input_remain: state.inner.avail_in as usize,
output_remain: state.inner.avail_out as usize,
status: match result {
sys::Z_OK => match state.inner.avail_in {
0 => Ok(DecodeStatus::NeedInput),
_ => Ok(DecodeStatus::NeedOutput),
},
sys::Z_STREAM_END => Ok(DecodeStatus::Finished),
sys::Z_BUF_ERROR => Ok(DecodeStatus::NeedOutput),
other => Err(crate::decoder::DecodeError(other as _)),
},
}
}};
}
#[cfg(any(feature = "zlib", feature = "zlib-static", feature = "zlib-ng", feature = "zlib-rust"))]
mod zlib_common;
#[cfg(any(feature = "zlib", feature = "zlib-static", feature = "zlib-ng", feature = "zlib-rust"))]
pub use zlib_common::ZlibMode;
#[cfg(feature = "brotli-rust")]
mod brotli;
#[cfg(feature = "brotli-c")]
mod brotli_c;
#[cfg(any(feature = "zlib", feature = "zlib-static"))]
mod zlib;
#[cfg(feature = "zlib-ng")]
mod zlib_ng;
#[cfg(feature = "zlib-rust")]
mod zlib_rust;
#[cfg(feature = "zstd")]
mod zstd;
#[cfg(feature = "zstd")]
pub use zstd::ZstdOptions;
impl<const N: usize> crate::Buffer<N> {
pub fn decode(&mut self, decoder: &mut Decoder, input: &[u8]) -> Result<(usize, DecodeStatus), DecodeError> {
let spare_capacity = self.spare_capacity_mut();
let spare_capacity_len = spare_capacity.len();
let result = decoder.decode_uninit(input, spare_capacity);
match result.status {
Ok(status) => {
self.cursor = self.cursor + spare_capacity_len - result.output_remain;
Ok((input.len() - result.input_remain, status))
}
Err(error) => Err(error),
}
}
}