Skip to main content

pdf_redact/
error.rs

1//! Error types for `pdf-redact` operations.
2
3// Copyright (c) 2026 Innovation Trigger B.V.
4//
5// PDFluent is available under two licences, at your option: the GNU AGPLv3, or
6// the PDFluent Commercial Licence. See the LICENSE file in this repository --
7// that file travels with the copy you received, which a URL does not.
8
9use thiserror::Error;
10
11/// Errors returned by the `pdf-redact` crate while marking or applying
12/// content redaction.
13///
14/// Redaction is high-stakes (compliance, legal disclosure) so each variant
15/// describes a *refusal to proceed* rather than a best-effort fallback. If
16/// you receive any variant, the input is left untouched.
17#[derive(Debug, Error)]
18pub enum RedactError {
19    /// The underlying PDF byte stream could not be parsed.
20    ///
21    /// Typically a malformed cross-reference table, a truncated stream, or
22    /// an encrypted PDF that was not opened with the right password.
23    #[error("PDF error: {0}")]
24    Pdf(#[from] lopdf::Error),
25
26    /// An I/O error occurred while reading the source PDF or writing the
27    /// redacted output.
28    #[error("IO error: {0}")]
29    Io(#[from] std::io::Error),
30
31    /// The caller asked to redact a page index that does not exist in the
32    /// document.
33    ///
34    /// Fields: `(requested_page, total_pages)`. Page numbers are 1-based.
35    #[error("page {0} out of range (document has {1} pages)")]
36    PageOutOfRange(u32, u32),
37
38    /// The redaction call had no regions and no search query — nothing to
39    /// remove. Returned eagerly so callers do not silently produce
40    /// no-op output.
41    #[error("no redaction areas specified")]
42    NoAreas,
43
44    /// An image embedded inside a redaction region uses a PDF stream filter
45    /// that the redactor cannot rewrite (for example JBIG2 or some JPEG2000
46    /// profiles). The redaction is aborted because partially-stripped
47    /// images would leak content. The caller can either rasterise the page
48    /// before redacting or skip the affected page.
49    #[error("unsupported image filter: {0}")]
50    UnsupportedImageFilter(String),
51
52    /// A page touched by the redaction has a `/ToUnicode` CMap whose shape
53    /// the conservative `pdf-redact` parser cannot rewrite safely.
54    ///
55    /// The redactor refuses to silently drop the CMap because that would
56    /// break text-extraction tools downstream. The caller's options are
57    /// to rasterise the page first or to redact a different page range
58    /// that does not include this font.
59    #[error(
60        "unsupported /ToUnicode CMap on redacted page (font {font_resource_name}): \
61         redaction strip refuses to silently drop /ToUnicode; CMap shape not understood by the \
62         conservative pdf-redact parser ({reason})"
63    )]
64    UnsupportedToUnicodeCMap {
65        /// The PDF resource name of the font whose CMap is unsupported,
66        /// e.g. `"F1"`.
67        font_resource_name: String,
68        /// A human-readable reason for the parser's refusal, e.g.
69        /// `"surrogate pair without continuation"`.
70        reason: String,
71    },
72
73    /// A non-categorised redaction failure. Reserved for cases the more
74    /// specific variants do not cover; the message describes the situation.
75    #[error("{0}")]
76    Other(String),
77}
78
79/// Convenience `Result` alias for fallible `pdf-redact` operations.
80pub type Result<T> = std::result::Result<T, RedactError>;