use std::fmt;
use crate::limits::LimitKind;
use crate::object::ObjId;
use crate::source::SourceError;
#[derive(Debug, Clone, PartialEq)]
pub enum Error {
Source(SourceError),
Syntax {
offset: u64,
message: &'static str,
},
UnexpectedEof,
Limit(LimitKind),
NoXref,
NoRoot,
MissingObject(ObjId),
WrongType {
expected: &'static str,
found: &'static str,
},
Filter(&'static str),
UnsupportedEncryption(String),
InvalidPassword,
}
impl Error {
pub fn syntax(offset: u64, message: &'static str) -> Self {
Self::Syntax { offset, message }
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Source(e) => e.fmt(f),
Self::Syntax { offset, message } => {
write!(f, "syntax error at byte {offset}: {message}")
}
Self::UnexpectedEof => f.write_str("unexpected end of input"),
Self::Limit(kind) => write!(f, "{kind} limit exceeded"),
Self::NoXref => f.write_str("no cross-reference data or objects found"),
Self::NoRoot => f.write_str("trailer has no document catalog (/Root)"),
Self::MissingObject(id) => write!(f, "object {} {} not found", id.num, id.generation),
Self::WrongType { expected, found } => {
write!(f, "expected {expected}, found {found}")
}
Self::Filter(msg) => write!(f, "stream decoding failed: {msg}"),
Self::UnsupportedEncryption(msg) => write!(f, "unsupported encryption: {msg}"),
Self::InvalidPassword => f.write_str("incorrect password"),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Source(e) => Some(e),
_ => None,
}
}
}
impl From<SourceError> for Error {
fn from(e: SourceError) -> Self {
Self::Source(e)
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display() {
assert_eq!(
Error::syntax(5, "expected dictionary").to_string(),
"syntax error at byte 5: expected dictionary"
);
assert_eq!(
Error::Limit(LimitKind::Depth).to_string(),
"nesting depth limit exceeded"
);
assert_eq!(
Error::MissingObject(ObjId::new(3, 0)).to_string(),
"object 3 0 not found"
);
assert!(std::error::Error::source(&Error::Source(SourceError::new("x"))).is_some());
assert!(std::error::Error::source(&Error::NoRoot).is_none());
}
}