Skip to main content

pdfluent_lopdf/
error.rs

1use thiserror::Error;
2
3use crate::encodings::cmap::UnicodeCMapError;
4use crate::{ObjectId, encryption};
5
6pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug, Error)]
9pub enum Error {
10    /// Lopdf does not (yet) implement a needed feature.
11    #[error(
12        "missing feature of lopdf: {0}; please open an issue at https://github.com/J-F-Liu/lopdf/ to let the developers know of your usecase"
13    )]
14    Unimplemented(&'static str),
15
16    /// An Object has the wrong type, e.g. the Object is an Array where a Name would be expected.
17    #[error("object has wrong type; expected type {expected} but found type {found}")]
18    ObjectType {
19        expected: &'static str,
20        found: &'static str,
21    },
22    #[error("dictionary has wrong type: ")]
23    DictType {
24        expected: &'static str,
25        found: String,
26    },
27    /// PDF document is already encrypted.
28    #[error("PDF document is already encrypted")]
29    AlreadyEncrypted,
30    /// The encountered character encoding is invalid.
31    #[error("invalid character encoding")]
32    CharacterEncoding,
33    /// The stream couldn't be decompressed.
34    #[error("couldn't decompress stream {0}")]
35    Decompress(#[from] DecompressError),
36    /// Failed to parse input.
37    #[error("couldn't parse input: {0}")]
38    Parse(#[from] ParseError),
39    /// Error when decrypting the contents of the file
40    #[error("decryption error: {0}")]
41    Decryption(#[from] encryption::DecryptionError),
42    /// Dictionary key was not found.
43    #[error("missing required dictionary key \"{0}\"")]
44    DictKey(String),
45    /// Invalid inline image.
46    #[error("invalid inline image: {0}")]
47    InvalidInlineImage(String),
48    /// Invalid document outline.
49    #[error("invalid document outline: {0}")]
50    InvalidOutline(String),
51    /// Invalid stream.
52    #[error("invalid stream: {0}")]
53    InvalidStream(String),
54    /// Invalid object stream.
55    #[error("invalid object stream: {0}")]
56    InvalidObjectStream(String),
57    /// Byte offset in stream or file is invalid.
58    #[error("invalid byte offset")]
59    InvalidOffset(usize),
60    /// IO error
61    #[error("IO error: {0}")]
62    IO(#[from] std::io::Error),
63    // TODO: Maybe remove, as outline is not required in spec.
64    /// PDF document has no outline.
65    #[error("PDF document does not have an outline")]
66    NoOutline,
67    /// PDF document is not encrypted.
68    #[error("PDF document is not encrypted")]
69    NotEncrypted,
70    /// Invalid password provided for encrypted PDF.
71    #[error("invalid password for encrypted PDF")]
72    InvalidPassword,
73    /// Missing xref entry.
74    #[error("missing xref entry")]
75    MissingXrefEntry,
76    /// The Object ID was not found.
77    #[error("object ID {} {} not found", .0.0, .0.1)]
78    ObjectNotFound(ObjectId),
79    /// Dereferencing object failed due to a reference cycle.
80    #[error("reference cycle with object ID {} {}", .0.0, .0.1)]
81    ReferenceCycle(ObjectId),
82    /// Page number was not found in document.
83    #[error("page number not found")]
84    PageNumberNotFound(u32),
85    /// Numeric type cast failed.
86    #[error("numberic type cast failed: {0}")]
87    NumericCast(String),
88    /// Dereferencing object reached the limit.
89    /// This might indicate a reference loop.
90    #[error("dereferencing object reached limit, may indicate a reference cycle")]
91    ReferenceLimit,
92    /// Decoding text string failed.
93    #[error("decoding text string failed")]
94    TextStringDecode,
95    /// Error while parsing cross reference table.
96    #[error("failed parsing cross reference table: {0}")]
97    Xref(XrefError),
98    /// Invalid indirect object while parsing at offset.
99    #[error("invalid indirect object at byte offset {offset}")]
100    IndirectObject { offset: usize },
101    /// Found object ID does not match expected object ID.
102    #[error("found object ID does not match expected object ID")]
103    ObjectIdMismatch,
104    /// Error when handling images.
105    #[cfg(feature = "embed_image")]
106    #[error("image error: {0}")]
107    Image(#[from] image::ImageError),
108    /// Syntax error while processing the content stream.
109    #[error("syntax error in content stream: {0}")]
110    Syntax(String),
111    /// Could not parse ToUnicodeCMap.
112    #[error("failed parsing ToUnicode CMap: {0}")]
113    ToUnicodeCMap(#[from] UnicodeCMapError),
114    #[error("converting integer: {0}")]
115    TryFromInt(#[from] std::num::TryFromIntError),
116    /// Encountered an unsupported security handler.
117    #[error("unsupported security handler")]
118    UnsupportedSecurityHandler(Vec<u8>),
119    /// Input buffer exceeds the configured per-document size limit.
120    ///
121    /// Returned by `Document::load_mem_with_options` / `load_with_options`
122    /// when the input size exceeds `LoadOptions::max_file_bytes`.
123    #[error("document too large: {size} bytes exceeds limit of {limit} bytes")]
124    DocumentTooLarge { size: usize, limit: usize },
125    /// An ObjStm stream could not be decompressed during lazy resolution.
126    #[error("failed to decompress ObjStm object {container_id}")]
127    ObjStmDecompress { container_id: u32 },
128    /// Decompressed stream exceeds the per-stream size limit (LOPDF-ZBOMB-01).
129    ///
130    /// Returned when a FlateDecode or LZWDecode stream expands beyond
131    /// `MAX_DECOMPRESSED_BYTES`, preventing zip-bomb DoS attacks.
132    #[error("decompressed stream too large: exceeds {limit} bytes")]
133    StreamTooLarge { limit: usize },
134}
135
136#[derive(Error, Debug)]
137pub enum DecompressError {
138    #[error("decoding ASCII85 failed: {0}")]
139    Ascii85(&'static str),
140    #[error("decoding ASCIIHex failed: {0}")]
141    AsciiHex(&'static str),
142}
143
144#[derive(Error, Debug)]
145pub enum ParseError {
146    #[error("unexpected end of input")]
147    EndOfInput,
148    #[error("invalid content stream")]
149    InvalidContentStream,
150    #[error("invalid file header")]
151    InvalidFileHeader,
152    #[error("invalid file trailer")]
153    InvalidTrailer,
154    #[error("invalid cross reference table")]
155    InvalidXref,
156}
157
158#[derive(Debug, Error)]
159pub enum XrefError {
160    /// Could not find start of cross reference table.
161    #[error("invalid start value")]
162    Start,
163    /// The trailer's "Prev" field was invalid.
164    #[error("invalid start value in Prev field")]
165    PrevStart,
166    /// The trailer's "XRefStm" field was invalid.
167    #[error("invalid start value of XRefStm")]
168    StreamStart,
169}