1use std::fmt::Display;
4
5use smol_str::SmolStr;
6use write_fonts::{BuilderError, read::ReadError};
7
8use crate::{DiagnosticSet, parse::SourceLoadError};
9
10#[derive(Clone, Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum UfoGlyphOrderError {
14 #[error("No public.glyphOrder key in lib.plist")]
16 KeyNotSet,
17 #[error("public.glyphOrder exists, but is not an array of strings")]
19 Malformed,
20 #[error(transparent)]
22 BadGlyphOrder(#[from] GlyphOrderError),
23}
24
25#[derive(Clone, Debug, thiserror::Error)]
27#[non_exhaustive]
28pub enum FontGlyphOrderError {
29 #[error("Failed to read font data: '{0}'")]
31 ReadError(
32 #[from]
33 #[source]
34 ReadError,
35 ),
36 #[error("The post table exists, but did not include all glyph names")]
38 MissingNames,
39 #[error(transparent)]
41 BadGlyphOrder(#[from] GlyphOrderError),
42}
43
44#[derive(Clone, Debug, thiserror::Error)]
46#[non_exhaustive]
47pub enum GlyphOrderError {
48 #[error("Invalid name '{name}' in glyph order")]
50 #[allow(missing_docs)]
51 NameError { name: SmolStr },
52 #[error("The first glyph must be '.notdef'")]
54 MissingNotDef,
55 #[error("Order contains too many glyphs ({found})")]
56 #[allow(missing_docs)]
57 TooManyGlyphs { found: u32 },
58}
59
60#[derive(Debug, thiserror::Error)]
62#[allow(missing_docs)]
63#[non_exhaustive]
64pub enum CompilerError {
65 #[error(transparent)]
66 SourceLoad(#[from] SourceLoadError),
67 #[error("FEA parsing failed with {} errors", .0.messages.len())]
68 ParseFail(DiagnosticSet),
69 #[error("FEA validation failed with {} errors", .0.messages.len())]
70 ValidationFail(DiagnosticSet),
71 #[error("FEA compilation failed with {} errors", .0.messages.len())]
72 CompilationFail(DiagnosticSet),
73 #[error(transparent)]
74 WriteFail(#[from] BuilderError),
75}
76
77impl CompilerError {
78 pub fn display_verbose(&self) -> impl Display + '_ {
80 struct Verbose<'a>(&'a CompilerError);
81 impl std::fmt::Display for Verbose<'_> {
82 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
83 write!(f, "{}", self.0)?;
84 if let Some(diagnostics) = self.0.diagnostics() {
85 write!(f, "\n{}", diagnostics.display())?;
86 }
87 Ok(())
88 }
89 }
90 Verbose(self)
91 }
92
93 pub fn diagnostics(&self) -> Option<&DiagnosticSet> {
95 match self {
96 CompilerError::ParseFail(x)
97 | CompilerError::ValidationFail(x)
98 | CompilerError::CompilationFail(x) => Some(x),
99 _ => None,
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
110 fn assert_compiler_error_is_send() {
111 fn send_me_baby<T: Send>() {}
112 send_me_baby::<CompilerError>();
113 }
114}