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}