extern crate alloc;
mod archive_extra_data_record;
mod central_directory_header;
mod data_descriptor;
mod digital_signature;
mod end_of_central_directory;
mod extensible_data;
mod local_file_header;
mod zip64_end_of_central_directory;
#[cfg(feature = "std")] use std::error::Error;
#[derive(Debug, PartialEq)]
pub enum FixedSizeError {
UnsufficientExactBytes(usize),
}
#[derive(Debug, PartialEq)]
pub enum DynamicSizeError {
NotContiguous(usize),
UnsufficientExactBytes(usize),
UnsufficientAtLeastBytes(usize),
}
#[derive(Debug, PartialEq)]
pub enum DynamicSizeTotalSizeError {
Dynamic(DynamicSizeError),
TotalSizeInFieldIsInvalid,
}
pub(super) fn preview_u16_from_buf(buf: &[u8], pos: usize) -> Option<u16> {
buf.get(pos..pos + 2)
.map(|src| unsafe { u16::from_le_bytes(*(src as *const _ as *const [_; 2])) })
}
pub(super) fn validate_length<E, T: Fn(usize) -> E>(have: usize, want: usize, e: T) -> Result<(), E> {
if have < want {
return Err(e(want - have));
}
Ok(())
}
pub trait Parse {
type Error;
fn from_buf<T: bytes::Buf>(buf: &mut T) -> Result<Self, Self::Error>
where
Self: Sized;
fn to_buf<T: bytes::BufMut>(&self, buf: &mut T) -> Result<(), Self::Error>;
}
pub trait ParseExtend {
type Fixed;
type Error;
fn from_buf_fixed<T: bytes::Buf>(buf: &mut T, fixed: Self::Fixed) -> Result<Self, (Self::Error, Self::Fixed)>
where
Self: Sized;
}
impl FixedSizeError {
pub(super) fn in_dynamic(self) -> DynamicSizeError {
match self {
FixedSizeError::UnsufficientExactBytes(b) => DynamicSizeError::UnsufficientAtLeastBytes(b),
}
}
}
impl From<DynamicSizeError> for DynamicSizeTotalSizeError {
fn from(value: DynamicSizeError) -> Self { DynamicSizeTotalSizeError::Dynamic(value) }
}
impl core::fmt::Display for FixedSizeError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
FixedSizeError::UnsufficientExactBytes(n) => write!(
f,
"Unsufficient Bytes to parse structure, the buffer needs to have {n} additional bytes to parse"
),
}
}
}
impl core::fmt::Display for DynamicSizeError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
DynamicSizeError::NotContiguous(n) => write!(
f,
"Bytes support data not beeing Continous, however to peek data its required that the data is within \
the first chunk of data. You need to reorganize the underlying data structure so that the first {n} \
bytes are within the first chun."
),
DynamicSizeError::UnsufficientExactBytes(n) => write!(
f,
"Unsufficient Bytes to parse structure, the buffer needs to have {n} additional bytes to parse"
),
DynamicSizeError::UnsufficientAtLeastBytes(n) => write!(
f,
"Unsufficient Bytes to parse structure, the buffer needs to have at least {n} additional bytes to \
parse, probably even more bytes are needed. An exact estimation cannot be made yet"
),
}
}
}
impl core::fmt::Display for DynamicSizeTotalSizeError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
DynamicSizeTotalSizeError::Dynamic(e) => write!(f, "{e}"),
DynamicSizeTotalSizeError::TotalSizeInFieldIsInvalid => write!(
f,
"The Record contains an corrupt field stating the total size is lower than the minimum size"
),
}
}
}
#[cfg(feature = "std")]
impl Error for FixedSizeError {}
#[cfg(feature = "std")]
impl Error for DynamicSizeError {}
#[cfg(feature = "std")]
impl Error for DynamicSizeTotalSizeError {}
#[inline(always)]
#[allow(clippy::manual_find)] pub fn find_next_signature(buf: &[u8], signature: [u8; 4]) -> Option<usize> {
for i in 0..buf.len() - 4 {
if buf[i] == signature[0]
&& buf[i + 1] == signature[1]
&& buf[i + 2] == signature[2]
&& buf[i + 3] == signature[3]
{
return Some(i);
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_dont_panic() {
let mut buf = vec![0; 20000];
use std::io::Write;
write!(buf, "{}", FixedSizeError::UnsufficientExactBytes(1)).unwrap();
write!(buf, "{}", DynamicSizeError::NotContiguous(2)).unwrap();
write!(buf, "{}", DynamicSizeError::UnsufficientExactBytes(3)).unwrap();
write!(buf, "{}", DynamicSizeError::UnsufficientAtLeastBytes(4)).unwrap();
write!(
buf,
"{}",
DynamicSizeTotalSizeError::Dynamic(DynamicSizeError::NotContiguous(5))
)
.unwrap();
write!(buf, "{}", DynamicSizeTotalSizeError::TotalSizeInFieldIsInvalid).unwrap();
}
}