Skip to main content

pdfrum_parser/
error.rs

1//! What can go wrong reading a file.
2//!
3//! Short by design. Almost everything this crate does about damage is a
4//! *recovery* recorded in `Diagnostics`, not a failure, so the error type
5//! only names the conditions under which reading genuinely stops.
6
7use pdfrum_common::{LimitExceeded, PageIndex};
8use pdfrum_object::ObjRef;
9
10/// A failure below the document level: a token that is not an object, a
11/// cross-reference section that cannot be read, a fetch that finds nothing.
12#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
13#[non_exhaustive]
14pub enum Error {
15    /// The bytes at this position are not the start of any object.
16    #[error("no object at offset {0}")]
17    NoObject(u64),
18
19    /// Objects nested deeper than the configured limit.
20    #[error("object nesting deeper than {0}")]
21    TooDeep(u32),
22
23    /// No cross-reference information could be read or reconstructed.
24    #[error("no usable cross-reference information")]
25    XrefBroken,
26
27    /// The trailer named no catalog, or the object it named is not one.
28    #[error("no document catalog")]
29    NoCatalog,
30
31    /// A reference names an object the cross-reference table has no entry
32    /// for, has marked free, or whose body would not parse.
33    #[error("no object for reference {}:{}", .0.num, .0.generation)]
34    Unresolved(ObjRef),
35
36    /// This fetch re-entered one already in progress.
37    #[error("reference cycle while fetching {}:{}", .0.num, .0.generation)]
38    Cycle(ObjRef),
39
40    /// A page index past the document's page count, or one whose tree walk
41    /// found nothing.
42    #[error("no page at index {0}")]
43    NoPage(PageIndex),
44
45    /// The caller's `Limits::deadline` passed while the cross-reference was
46    /// being rebuilt by scanning the file.
47    #[error(transparent)]
48    Limit(LimitExceeded),
49}
50
51impl From<Error> for pdfrum_object::Error {
52    fn from(e: Error) -> Self {
53        match e {
54            Error::Cycle(r) => Self::RefLoop(r),
55            Error::Unresolved(r) => Self::UnresolvedRef(r),
56            // Everything else reaching an accessor reads as a dangling
57            // reference, which is how a damaged file already behaves.
58            _ => Self::UnresolvedRef(ObjRef::new(0, 0)),
59        }
60    }
61}