write_fonts/error.rs
1//! Errors that occur during writing
2
3use std::sync::Arc;
4
5use crate::{graph::Graph, validate::ValidationReport};
6
7/// A packing could not be found that satisfied all offsets
8///
9/// If the "dot2" feature is enabled, you can use the `write_graph_viz` method
10/// on this error to dump a text representation of the graph to disk. You can
11/// then use graphviz to convert this into an image. For example, to create
12/// an SVG, you might use, `dot -v -Tsvg failure.dot2 > failure.svg`, where
13/// 'failure.dot2' is the path where you dumped the graph.
14#[derive(Clone)]
15pub struct PackingError {
16 // this is Arc so that we can clone and still be sent between threads.
17 pub(crate) graph: Arc<Graph>,
18}
19
20/// An error occurred while writing this table
21#[derive(Debug, Clone)]
22pub enum Error {
23 /// The table failed a validation check
24 ///
25 /// This indicates that the table contained invalid or inconsistent data
26 /// (for instance, it had an explicit version set, but contained fields
27 /// not present in that version).
28 ValidationFailed(ValidationReport),
29 /// The table contained overflowing offsets
30 ///
31 /// This indicates that an ordering could not be found that allowed all
32 /// tables to be reachable from their parents. See [`PackingError`] for
33 /// more details.
34 PackingFailed(PackingError),
35}
36
37impl PackingError {
38 /// Write a graphviz file representing the failed packing to the provided path.
39 ///
40 /// Has the same semantics as [`std::fs::write`].
41 #[cfg(feature = "dot2")]
42 pub fn write_graph_viz(&self, path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
43 self.graph.write_graph_viz(path)
44 }
45}
46
47impl std::fmt::Display for Error {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 Error::ValidationFailed(report) => report.fmt(f),
51 Error::PackingFailed(error) => error.fmt(f),
52 }
53 }
54}
55
56impl std::fmt::Display for PackingError {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(
59 f,
60 "Table packing failed with {} overflows",
61 self.graph.find_overflows().len()
62 )
63 }
64}
65
66impl std::fmt::Debug for PackingError {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 write!(f, "{self}")
69 }
70}
71
72impl std::error::Error for PackingError {}
73impl std::error::Error for Error {}
74
75impl From<ValidationReport> for Error {
76 fn from(value: ValidationReport) -> Self {
77 Error::ValidationFailed(value)
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 /// Some users, notably fontmake-rs, like Send errors.
86 #[test]
87 fn assert_compiler_error_is_send() {
88 fn send_me_baby<T: Send>() {}
89 send_me_baby::<Error>();
90 }
91}