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}