structured_pades/error.rs
1//! Located syntax, ambiguity, unsupported capability and processing refusals.
2
3use crate::source::Location;
4use core::fmt;
5use structured_asn1::memory::MemoryError;
6
7/// A concrete PDF grammar or document-structure violation.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Syntax {
10 /// Missing or malformed file header.
11 Header,
12 /// Unexpected token for the selected grammar.
13 Token,
14 /// Value or delimiter extends beyond its original source.
15 End,
16 /// Invalid integer or real spelling.
17 Number,
18 /// Invalid name escape or forbidden zero byte.
19 Name,
20 /// Invalid literal or hexadecimal string.
21 String,
22 /// Invalid dictionary entry or conflicting duplicate key.
23 Dictionary,
24 /// Invalid stream extent, encoding or decoding parameters.
25 Stream,
26 /// Invalid indirect object definition or reference identity.
27 Object,
28 /// Invalid cross-reference section or object location.
29 CrossReference,
30 /// Invalid terminal startxref record.
31 StartXref,
32 /// Invalid document trailer.
33 Trailer,
34 /// The carried signature container has the wrong format or extent.
35 Container,
36 /// Reference or cross-reference chain returns to itself.
37 Cycle,
38}
39
40/// Caller-selected mechanism limit, separate from malformed syntax.
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub enum Limit {
43 /// Container or resolution nesting limit.
44 Depth,
45 /// Cumulative original and decoded object count.
46 Objects,
47 /// Cumulative revision count.
48 Revisions,
49 /// Cumulative decoded output allowance.
50 Decoded,
51}
52
53/// An explicitly unavailable processing capability.
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum Unsupported {
56 /// Requested stream filter has no selected structural decoder.
57 Filter,
58 /// External stream bytes were not supplied by a caller.
59 ExternalStream,
60 /// Required encrypted source bytes are unavailable.
61 Encryption,
62 /// A number cannot be represented for this particular query.
63 NumericRange,
64}
65
66/// Independent failure classes; processing causes cannot become syntax faults.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum ErrorKind {
69 /// Unreadable syntax with its actual domain and range.
70 Syntax(Syntax),
71 /// Two incompatible readings; selecting the first would lose meaning.
72 Ambiguous(Syntax),
73 /// Caller-selected resource count exhausted before the operation.
74 Limit(Limit),
75 /// Actual shared allocator, capacity, or current/source work refusal.
76 Resource(MemoryError),
77 /// Required capability is explicitly unavailable.
78 Unsupported(Unsupported),
79 /// A caller mixed source/session/document identities.
80 Foreign,
81}
82
83/// Failure preserving both logical coordinates and honest physical enclosure.
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub struct Error {
86 /// Original failure classification and cause.
87 pub kind: ErrorKind,
88 /// Original range, with its source discriminator.
89 pub location: Location,
90}
91impl Error {
92 /// Processing and source misuse cannot become a recoverable syntax slot.
93 #[must_use]
94 pub fn is_terminal(&self) -> bool {
95 matches!(
96 self.kind,
97 ErrorKind::Limit(_) | ErrorKind::Resource(_) | ErrorKind::Foreign
98 )
99 }
100}
101
102impl fmt::Display for Error {
103 fn fmt(&self, output: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(output, "{:?} at {:?}", self.kind, self.location)
105 }
106}
107
108impl core::error::Error for Error {}
109
110/// Recoverable original format fault, never an allocator/work/processing cause.
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112pub struct Fault {
113 /// Specific readable format violation.
114 pub code: Syntax,
115 /// Original source location.
116 pub location: Location,
117}
118
119/// Result of a PDF mechanism operation.
120pub type Result<T> = core::result::Result<T, Error>;
121
122/// A format operation may fail independently in PDF processing or in the
123/// caller's asynchronous source. Opaque causes are never syntax diagnostics.
124#[derive(Debug)]
125pub enum ReadFailure<E> {
126 /// Original located PDF syntax, ambiguity, resource or capability cause.
127 Format(Error),
128 /// Original source snapshot/acquisition/resource cause and range.
129 Input(crate::range::InputError<E>),
130}
131impl<E> ReadFailure<E> {
132 /// Opaque acquisition, resource and source-identity refusals are terminal.
133 #[must_use]
134 pub fn is_terminal(&self) -> bool {
135 match self {
136 Self::Format(cause) => cause.is_terminal(),
137 Self::Input(_) => true,
138 }
139 }
140}
141
142impl<E> From<Error> for ReadFailure<E> {
143 fn from(error: Error) -> Self {
144 Self::Format(error)
145 }
146}
147
148impl<E> From<crate::range::InputError<E>> for ReadFailure<E> {
149 fn from(error: crate::range::InputError<E>) -> Self {
150 Self::Input(error)
151 }
152}