use raves_metadata_types::exif::{Field, ifd::IfdGroup, primitives::PrimitiveTy};
use crate::exif::ifd::RECURSION_LIMIT;
pub type ExifFatalResult<T> = Result<T, ExifFatalError>;
pub type ExifFieldResult = Result<Field, ExifFieldError>;
#[derive(Clone, Debug, PartialEq, PartialOrd, Hash)]
pub enum ExifFatalError {
NoByteOrderMarker {
len: u8,
},
WeirdByteOrderMarker {
found: [u8; 2],
},
NoTiffMagicNumber,
MagicNumberWasntTiff {
found: u16,
},
NoTiffHeaderOffset,
HeaderOffsetBeforeHeader,
NotEnoughDataForHeaderOffset,
IfdNoEntryCount,
IfdHadZeroFields,
IfdNoPointer,
SelfRecursion {
ifd_group: IfdGroup,
call_stack: Box<[Option<u32>; RECURSION_LIMIT as usize]>,
},
HitRecursionLimit {
ifd_group: IfdGroup,
call_stack: Box<[u32; RECURSION_LIMIT as usize]>,
},
}
impl winnow::error::ParserError<&[u8]> for ExifFatalError {
type Inner = Self;
fn from_input(_input: &&[u8]) -> Self {
unreachable!("we let winnow make an error without mapping. please report this!") }
fn into_inner(self) -> winnow::Result<Self::Inner, Self> {
Ok(self)
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Hash)]
pub enum ExifFieldError {
FieldNoTag,
FieldNoTy,
FieldUnknownType {
got: u16,
},
FieldNoCount,
FieldNoOffsetOrValue,
OffsetTooFar {
offset: u32,
},
OuttaData {
ty: PrimitiveTy,
},
}
impl core::fmt::Display for ExifFatalError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NoByteOrderMarker { len } => {
write!(f, "No byte order marker was found. len: `{len}`")
}
Self::WeirdByteOrderMarker { found } => match core::str::from_utf8(found.as_slice()) {
Ok(found_utf8_bom) => {
write!(f, "Got a weird byte-order marker: `{found_utf8_bom}`")
}
Err(e) => {
log::error!("Unknown byte-order marker was not ASCII! conversion err: {e}");
write!(f, "Got a weird byte-order marker - wasn't ASCII: {found:?}")
}
},
Self::NoTiffMagicNumber => {
f.write_str("No TIFF magic number found - the slice was likely cut short.")
}
Self::MagicNumberWasntTiff { found } => {
write!(f, "Magic number was not TIFF! got: `{found}`")
}
Self::NoTiffHeaderOffset => f.write_str("No TIFF header offset was found."),
Self::HeaderOffsetBeforeHeader => f.write_str(
"TIFF header offset asked us to move before the header. Likely a \
broken file - cannot continue parsing.",
),
Self::NotEnoughDataForHeaderOffset => {
f.write_str("Not enough data to skip to TIFF header offset.")
}
Self::IfdNoEntryCount => f.write_str("The IFD didn't say how many entries it has."),
Self::IfdHadZeroFields => {
f.write_str("The IFD told us it had zero fields, which is invalid.")
}
Self::IfdNoPointer => f.write_str("The IFD didn't give a pointer to the next entry."),
Self::SelfRecursion {
ifd_group,
call_stack,
} => write!(
f,
"An IFD attempted to self-recurse! This isn't permitted. \
group: {ifd_group:?}, call stack: {call_stack:#?}"
),
Self::HitRecursionLimit {
ifd_group,
call_stack,
} => write!(
f,
"An IFD recursed more than {RECURSION_LIMIT} times! \
This isn't allowed. \
group: {ifd_group:?}, call stack: {call_stack:?}"
),
}
}
}
impl core::fmt::Display for ExifFieldError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ExifFieldError::FieldNoTag => f.write_str("The field did not provide a tag."),
ExifFieldError::FieldNoTy => f.write_str("The field didn't provide a primitive type."),
ExifFieldError::FieldNoCount => {
f.write_str("The field didn't specify how many primitives it contains.")
}
ExifFieldError::FieldNoOffsetOrValue => {
f.write_str("The field didn't provide an offset or value.")
}
ExifFieldError::FieldUnknownType { got } => write!(
f,
"Encountered an unknown type while parsing n field! got: {got}"
),
ExifFieldError::OuttaData { ty } => write!(
f,
"Couldn't parse primitive - no more data in blob. ty: `{ty:?}`"
),
ExifFieldError::OffsetTooFar { offset } => write!(
f,
"Couldn't skip to offset - no more data in blob. offset: `{offset}`"
),
}
}
}
impl core::error::Error for ExifFatalError {}
impl core::error::Error for ExifFieldError {}