glifparser/
error.rs

1//! Provides main error type [`GlifParserError`] & its impl's
2
3#[cfg(feature = "mfek")]
4pub mod mfek;
5
6mod string;
7pub use string::*;
8
9use crate::point::PointType;
10
11use std::error::Error;
12use std::fmt::{Formatter, Display};
13use std::io;
14use std::rc::Rc;
15
16use xmltree::{ParseError, Error as XMLTreeError};
17#[cfg(feature = "glifserde")]
18use plist::Error as PlistError;
19
20pub type GlifParserResult<T> = Result<T, GlifParserError>;
21
22#[derive(Debug, Clone)]
23pub enum GlifParserError {
24    /// OS error when reading glif
25    GlifFileIoError(Option<Rc<io::Error>>),
26    /// Self-built Outline/Contour error.
27    GlifOutlineHasBadPointType{ci: usize, pi: usize, ptype: PointType},
28    GlifContourHasBadPointType{pi: usize, ptype: PointType},
29
30    /// Glif filename not set
31    GlifFilenameNotSet(String),
32    /// Glif filename doesn't match name in XML
33    GlifFilenameInsane(String),
34    /// Components of the glyph form a loop
35    GlifComponentsCyclical(String),
36    /// .glif has invalid <lib>
37    GlifLibError,
38
39    /// Glif isn't UTF8
40    GlifNotUtf8,
41    /// The XML making up the glif is invalid
42    XmlParseError(String),
43    /// The XML making up the glif is invalid
44    PedanticXmlParseError(String),
45    /// Failures when writing glif XML
46    XmlWriteError(String),
47    /// The XML is valid, but doesn't meet the UFO .glif spec
48    GlifInputError(String),
49
50    /// Image not yet read
51    ImageNotLoaded,
52    /// Image not PNG
53    ImageNotPNG,
54    /// Image not decodable
55    ImageNotDecodable,
56    /// OS error when reading image
57    ImageIoError(Option<Rc<io::Error>>),
58
59    /// Color (for guidelines, images, etc) not RGBA
60    ColorNotRGBA,
61    /// Error for use by parse() trait (FromStr)
62    TypeConversionError{req_type: &'static str, req_variant: String},
63
64    /// A requested point index is out of bounds
65    ContourLenOneUnexpected,
66    ContourLenZeroUnexpected,
67    PointIdxOutOfBounds{idx: usize, len: usize},
68    /// No previous on an open contour.
69    // usize value = contour length for these 2
70    ContourNoPrevious(usize),
71    /// No next on an open contour
72    ContourNoNext(usize),
73}
74
75impl Display for GlifParserError {
76    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { 
77        write!(f, "glifparser error: {}", match self {
78            Self::GlifFileIoError(ioe) => {
79                format!("System error when loading glif file: {:?}", ioe)
80            },
81            Self::GlifOutlineHasBadPointType{ci, pi, ptype} => {
82                format!("Bad point type {:?} in outline @({}, {}))", ptype, ci, pi)
83            },
84            Self::GlifContourHasBadPointType{pi, ptype} => {
85                format!("Bad point type {:?} in contour @{})", ptype, pi)
86            },
87            Self::GlifFilenameNotSet(s) => {
88                format!("Glyph filename not set: {}", &s)
89            },
90            Self::GlifFilenameInsane(s) => {
91                format!("Glyph filename not sane: {}", &s)
92            },
93            Self::GlifNotUtf8 => {
94                format!("Glyph not utf-8")
95            },
96            Self::GlifComponentsCyclical(s) => {
97                format!("Glyph components are cyclical: {}", &s)
98            },
99            Self::GlifLibError => {
100                format!("Glif <lib> invalid")
101            },
102
103            Self::XmlParseError(s) | Self::XmlWriteError(s) => {
104                format!("XML error: {}", &s)
105            },
106            Self::PedanticXmlParseError(s) => {
107                format!("XML error (requested pedantry, would not normally be an error): {}", &s)
108            },
109            Self::GlifInputError(s) => {
110                format!("Glif format spec error: {}", &s)
111            },
112
113            Self::ImageNotLoaded => {
114                format!("Tried to access data for image whose data hasn't been loaded")
115            },
116            Self::ImageNotPNG => {
117                format!("Image not formatted as PNG. The glif file format only supports PNG. If you want to support other types, you have to work on the data yourself.")
118            },
119            Self::ImageNotDecodable => {
120                format!("Image not decodable")
121            },
122            Self::ImageIoError(ioe) => {
123                format!("System error when loading image: {:?}", ioe)
124            },
125
126            Self::ColorNotRGBA => {
127                format!("Color not RGBA")
128            },
129
130            Self::TypeConversionError { req_type, req_variant } => {
131                format!("Type conversion error: {} not in {}", req_variant, req_type)
132            }
133
134            Self::PointIdxOutOfBounds { idx, len } => {
135                format!("The point index {} is out of bounds as self.len() == {}", idx, len)
136            }
137            Self::ContourLenOneUnexpected => {
138                format!("On a contour of length one, there's no previous/next point")
139            }
140            Self::ContourLenZeroUnexpected => {
141                format!("On an empty invalid contour (len == 0), there's no previous/next point")
142            }
143
144            Self::ContourNoPrevious(len) => {
145                format!("Asked for previous index of 0 on an open contour (len {})", len)
146            }
147
148            Self::ContourNoNext(len) => {
149                format!("Asked for next index of last point, {}, on an open contour", len)
150            }
151        })
152    }
153}
154
155// the parsing function in read_ufo_glif can only return this error type
156impl From<ParseError> for GlifParserError {
157    fn from(e: ParseError) -> Self {
158        Self::XmlParseError(format!("{}", e))
159    }
160}
161
162// . . . therefore it's OK to consider this a write-time error type
163impl From<XMLTreeError> for GlifParserError {
164    fn from(e: XMLTreeError) -> Self {
165        Self::XmlWriteError(format!("{}", e))
166    }
167}
168#[cfg(feature = "glifserde")]
169impl From<PlistError> for GlifParserError {
170    fn from(_e: PlistError) -> Self {
171        GlifParserError::GlifLibError
172    }
173}
174
175impl From<std::string::FromUtf8Error> for GlifParserError {
176    fn from(_: std::string::FromUtf8Error) -> Self {
177        Self::GlifNotUtf8
178    }
179}
180
181impl Error for GlifParserError {}