Skip to main content

pdfluent_jbig2/
error.rs

1//! Error types for JBIG2 decoding.
2
3use core::fmt;
4
5/// The main error type for JBIG2 decoding operations.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum DecodeError {
8    /// Errors related to reading/parsing data.
9    Parse(ParseError),
10    /// Errors related to file structure.
11    Format(FormatError),
12    /// Errors related to segment processing.
13    Segment(SegmentError),
14    /// Errors related to Huffman decoding.
15    Huffman(HuffmanError),
16    /// Errors related to region parameters.
17    Region(RegionError),
18    /// Errors related to template configuration.
19    Template(TemplateError),
20    /// Errors related to symbol handling.
21    Symbol(SymbolError),
22    /// Arithmetic overflow in calculations.
23    Overflow,
24    /// Feature not yet implemented.
25    Unsupported,
26}
27
28/// Errors related to reading/parsing data.
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum ParseError {
31    /// Unexpected end of input.
32    UnexpectedEof,
33}
34
35/// Errors related to file structure.
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum FormatError {
38    /// Invalid file header signature.
39    InvalidHeader,
40    /// Reserved bits are not zero.
41    ReservedBits,
42    /// Missing required page information segment.
43    MissingPageInfo,
44    /// Page height unknown with no stripe segments.
45    UnknownPageHeight,
46}
47
48/// Errors related to segment processing.
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum SegmentError {
51    /// Unknown or reserved segment type.
52    UnknownType,
53    /// Invalid referred-to segment count.
54    InvalidReferredCount,
55    /// Segment refers to a larger segment number.
56    InvalidReference,
57    /// Missing end marker for unknown-length region.
58    MissingEndMarker,
59    /// Missing required pattern dictionary.
60    MissingPatternDictionary,
61}
62
63/// Errors related to Huffman decoding.
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub enum HuffmanError {
66    /// Invalid Huffman code sequence.
67    InvalidCode,
68    /// Invalid Huffman table selection.
69    InvalidSelection,
70    /// Not enough referred Huffman tables.
71    MissingTables,
72    /// Unexpected out-of-band value.
73    UnexpectedOob,
74    /// Malformed Huffman table (JBIG2-HUF-01): a code path tries to branch
75    /// through a node that is already a leaf, indicating a collision in the
76    /// prefix-code assignment of a crafted JBIG2 stream.
77    MalformedTable,
78}
79
80/// Errors related to region parameters.
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum RegionError {
83    /// Invalid combination operator value.
84    InvalidCombinationOperator,
85    /// Region with invalid dimension.
86    InvalidDimension,
87    /// Gray-scale value exceeds pattern count.
88    GrayScaleOutOfRange,
89}
90
91/// Errors related to template configuration.
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub enum TemplateError {
94    /// An invalid template value was used.
95    Invalid,
96    /// Invalid adaptive template pixel location.
97    InvalidAtPixel,
98}
99
100/// Errors related to symbol handling.
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub enum SymbolError {
103    /// No symbols available for text region.
104    NoSymbols,
105    /// The symbol dictionary contains more symbols than expected.
106    TooManySymbols,
107    /// Symbol ID out of valid range.
108    OutOfRange,
109    /// Unexpected out-of-band value.
110    UnexpectedOob,
111    /// An invalid symbol was encountered.
112    Invalid,
113}
114
115impl fmt::Display for DecodeError {
116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117        match self {
118            Self::Parse(e) => write!(f, "{e}"),
119            Self::Format(e) => write!(f, "{e}"),
120            Self::Segment(e) => write!(f, "{e}"),
121            Self::Huffman(e) => write!(f, "{e}"),
122            Self::Region(e) => write!(f, "{e}"),
123            Self::Template(e) => write!(f, "{e}"),
124            Self::Symbol(e) => write!(f, "{e}"),
125            Self::Overflow => write!(f, "arithmetic overflow"),
126            Self::Unsupported => write!(f, "unsupported feature"),
127        }
128    }
129}
130
131impl fmt::Display for ParseError {
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        match self {
134            Self::UnexpectedEof => write!(f, "unexpected end of input"),
135        }
136    }
137}
138
139impl fmt::Display for FormatError {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        match self {
142            Self::InvalidHeader => write!(f, "invalid JBIG2 file header"),
143            Self::ReservedBits => write!(f, "reserved bits must be zero"),
144            Self::MissingPageInfo => write!(f, "missing page information segment"),
145            Self::UnknownPageHeight => write!(f, "page height unknown with no stripe segments"),
146        }
147    }
148}
149
150impl fmt::Display for SegmentError {
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        match self {
153            Self::UnknownType => write!(f, "unknown or reserved segment type"),
154            Self::InvalidReferredCount => write!(f, "invalid referred-to segment count"),
155            Self::InvalidReference => write!(f, "segment refers to larger segment number"),
156            Self::MissingEndMarker => write!(f, "missing end marker for unknown-length region"),
157            Self::MissingPatternDictionary => write!(f, "missing required pattern dictionary"),
158        }
159    }
160}
161
162impl fmt::Display for HuffmanError {
163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        match self {
165            Self::InvalidCode => write!(f, "invalid Huffman code"),
166            Self::InvalidSelection => write!(f, "invalid Huffman table selection"),
167            Self::MissingTables => write!(f, "not enough referred Huffman tables"),
168            Self::UnexpectedOob => write!(f, "unexpected out-of-band value"),
169            Self::MalformedTable => write!(
170                f,
171                "malformed Huffman table: code branches through a leaf node"
172            ),
173        }
174    }
175}
176
177impl fmt::Display for RegionError {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        match self {
180            Self::InvalidCombinationOperator => write!(f, "invalid combination operator"),
181            Self::InvalidDimension => write!(f, "invalid dimension value"),
182            Self::GrayScaleOutOfRange => write!(f, "gray-scale value exceeds pattern count"),
183        }
184    }
185}
186
187impl fmt::Display for TemplateError {
188    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189        match self {
190            Self::Invalid => write!(f, "invalid template value"),
191            Self::InvalidAtPixel => write!(f, "invalid adaptive template pixel location"),
192        }
193    }
194}
195
196impl fmt::Display for SymbolError {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        match self {
199            Self::NoSymbols => write!(f, "no symbols available"),
200            Self::OutOfRange => write!(f, "symbol ID out of range"),
201            Self::UnexpectedOob => write!(f, "unexpected out-of-band value"),
202            Self::TooManySymbols => write!(f, "symbol dictionary contains too many symbols"),
203            Self::Invalid => write!(f, "invalid symbol encountered"),
204        }
205    }
206}
207
208impl core::error::Error for DecodeError {}
209impl core::error::Error for ParseError {}
210impl core::error::Error for FormatError {}
211impl core::error::Error for SegmentError {}
212impl core::error::Error for HuffmanError {}
213impl core::error::Error for RegionError {}
214impl core::error::Error for TemplateError {}
215impl core::error::Error for SymbolError {}
216
217impl From<ParseError> for DecodeError {
218    fn from(e: ParseError) -> Self {
219        Self::Parse(e)
220    }
221}
222
223impl From<FormatError> for DecodeError {
224    fn from(e: FormatError) -> Self {
225        Self::Format(e)
226    }
227}
228
229impl From<SegmentError> for DecodeError {
230    fn from(e: SegmentError) -> Self {
231        Self::Segment(e)
232    }
233}
234
235impl From<HuffmanError> for DecodeError {
236    fn from(e: HuffmanError) -> Self {
237        Self::Huffman(e)
238    }
239}
240
241impl From<RegionError> for DecodeError {
242    fn from(e: RegionError) -> Self {
243        Self::Region(e)
244    }
245}
246
247impl From<TemplateError> for DecodeError {
248    fn from(e: TemplateError) -> Self {
249        Self::Template(e)
250    }
251}
252
253impl From<SymbolError> for DecodeError {
254    fn from(e: SymbolError) -> Self {
255        Self::Symbol(e)
256    }
257}
258
259/// Result type for JBIG2 decoding operations.
260pub type Result<T> = core::result::Result<T, DecodeError>;
261
262macro_rules! bail {
263    ($err:expr) => {
264        return Err($err.into())
265    };
266}
267
268macro_rules! err {
269    ($err:expr) => {
270        Err($err.into())
271    };
272}
273
274pub(crate) use bail;
275pub(crate) use err;