Skip to main content

read_fonts/ps/
error.rs

1//! Errors that may occur when processing PostScript fonts.
2
3use crate::ReadError;
4use core::fmt;
5
6/// Errors that are specific to PostScript processing.
7#[derive(Clone, Debug)]
8pub enum Error {
9    InvalidFontFormat,
10    InvalidIndexOffsetSize(u8),
11    ZeroOffsetInIndex,
12    InvalidVariationStoreIndex(u16),
13    StackOverflow,
14    StackUnderflow,
15    InvalidStackAccess(usize),
16    ExpectedI32StackEntry(usize),
17    InvalidNumber,
18    InvalidDictOperator(u8),
19    InvalidCharstringOperator(u8),
20    CharstringNestingDepthLimitExceeded,
21    MissingSubroutines,
22    MissingBlendState,
23    MissingFdArray,
24    MissingPrivateDict,
25    MissingCharstrings,
26    MissingCharset,
27    InvalidSeacCode(i32),
28    Read(ReadError),
29}
30
31impl From<ReadError> for Error {
32    fn from(value: ReadError) -> Self {
33        Self::Read(value)
34    }
35}
36
37impl fmt::Display for Error {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            Self::InvalidFontFormat => {
41                write!(f, "invalid font format")
42            }
43            Self::InvalidIndexOffsetSize(size) => {
44                write!(f, "invalid offset size of {size} for INDEX (expected 1-4)")
45            }
46            Self::ZeroOffsetInIndex => {
47                write!(f, "invalid offset of 0 in INDEX (must be >= 1)")
48            }
49            Self::InvalidVariationStoreIndex(index) => {
50                write!(
51                    f,
52                    "variation store index {index} referenced an invalid variation region"
53                )
54            }
55            Self::StackOverflow => {
56                write!(f, "attempted to push a value to a full stack")
57            }
58            Self::StackUnderflow => {
59                write!(f, "attempted to pop a value from an empty stack")
60            }
61            Self::InvalidStackAccess(index) => {
62                write!(f, "invalid stack access for index {index}")
63            }
64            Self::ExpectedI32StackEntry(index) => {
65                write!(f, "attempted to read an integer at stack index {index}, but found a fixed point value")
66            }
67            Self::InvalidNumber => {
68                write!(f, "number is in an invalid format")
69            }
70            Self::InvalidDictOperator(operator) => {
71                write!(f, "dictionary operator {operator} is invalid")
72            }
73            Self::InvalidCharstringOperator(operator) => {
74                write!(f, "charstring operator {operator} is invalid")
75            }
76            Self::CharstringNestingDepthLimitExceeded => {
77                write!(
78                    f,
79                    "exceeded subroutine nesting depth limit {} while evaluating a charstring",
80                    crate::ps::cs::NESTING_DEPTH_LIMIT
81                )
82            }
83            Self::MissingSubroutines => {
84                write!(
85                    f,
86                    "encountered a callsubr operator but no subroutine index was provided"
87                )
88            }
89            Self::MissingBlendState => {
90                write!(
91                    f,
92                    "encountered a blend operator but no blend state was provided"
93                )
94            }
95            Self::MissingFdArray => {
96                write!(f, "CFF table does not contain a font dictionary index")
97            }
98            Self::MissingPrivateDict => {
99                write!(f, "CFF table does not contain a private dictionary")
100            }
101            Self::MissingCharstrings => {
102                write!(f, "CFF table does not contain a charstrings index")
103            }
104            Self::MissingCharset => {
105                write!(f, "CFF table does not contain a valid charset")
106            }
107            Self::InvalidSeacCode(code) => {
108                write!(f, "seac code {code} is not valid")
109            }
110            Self::Read(err) => write!(f, "{err}"),
111        }
112    }
113}
114
115impl core::error::Error for Error {
116    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
117        match self {
118            Self::Read(err) => Some(err),
119            _ => None,
120        }
121    }
122}