rusty_figlet/error.rs
1//! Library error type for `rusty-figlet`.
2//!
3//! [`FigletError`] is the unified error type returned by every fallible
4//! public API in this crate. It is marked `#[non_exhaustive]` so that
5//! additive variants in future releases remain non-breaking under SemVer
6//! (per AD-013). Downstream consumers that pattern-match on the enum MUST
7//! include a wildcard `_` arm.
8//!
9//! `Send + Sync + 'static` is guaranteed at compile time (SC-009) so the
10//! error works across async `await` points and thread boundaries.
11
12use std::io;
13use std::path::PathBuf;
14
15/// All fallible operations in `rusty-figlet` return `Result<T, FigletError>`.
16///
17/// The enum is `#[non_exhaustive]` (per AD-013) so additive variants in
18/// future minor releases do NOT constitute a breaking change. Downstream
19/// matches MUST include a wildcard `_` arm:
20///
21/// ```rust
22/// use rusty_figlet::FigletError;
23/// fn describe(err: &FigletError) -> &'static str {
24/// match err {
25/// FigletError::FontNotFound { .. } => "missing font",
26/// FigletError::FontParse { .. } => "bad font file",
27/// FigletError::Io(_) => "io error",
28/// FigletError::WidthTooNarrow { .. } => "width too narrow",
29/// FigletError::Internal(_) => "internal error",
30/// _ => "unknown",
31/// }
32/// }
33/// ```
34///
35/// `Error::source()` returns `Some(&io::Error)` ONLY for the [`FigletError::Io`]
36/// variant; all other variants are leaf errors and return `None` from
37/// `source()`. `FontParse { line }` is 1-indexed and matches the convention
38/// used by upstream `figlet(6)` parse-error stderr messages.
39#[non_exhaustive]
40#[derive(Debug, thiserror::Error)]
41pub enum FigletError {
42 /// The requested font name (or path) could not be located.
43 ///
44 /// `name` is the user-supplied identifier; `searched` is the ordered
45 /// list of paths the resolver consulted, suitable for displaying in a
46 /// diagnostic message.
47 #[error("font not found: {name}; searched {searched:?}")]
48 FontNotFound {
49 /// Font name or path the user supplied (e.g. `"slant"`, `"./my.flf"`).
50 name: String,
51 /// Ordered list of paths inspected during font resolution.
52 searched: Vec<PathBuf>,
53 },
54
55 /// A `.flf` file failed to parse.
56 ///
57 /// `reason` is a short human description (e.g. `"bad signature"`,
58 /// `"missing endmark"`); `line` is the 1-indexed line number at which
59 /// the parser detected the problem.
60 #[error("font parse error at line {line}: {reason}")]
61 FontParse {
62 /// Short human-readable description of the parse failure.
63 reason: String,
64 /// 1-indexed line number where the parse error was detected.
65 line: u32,
66 },
67
68 /// Underlying I/O failure (file read, stdin, stdout).
69 ///
70 /// `Error::source()` returns the wrapped [`io::Error`] for this variant.
71 #[error("io error: {0}")]
72 Io(#[from] io::Error),
73
74 /// The requested width is too narrow to render the requested glyph(s).
75 ///
76 /// `needed` is the minimum width a single glyph requires; `given` is
77 /// the width the caller supplied.
78 #[error("width too narrow: needed {needed}, given {given}")]
79 WidthTooNarrow {
80 /// Minimum width required by the widest glyph.
81 needed: u32,
82 /// Width supplied by the caller.
83 given: u32,
84 },
85
86 /// An internal invariant was violated. Indicates a bug in the library;
87 /// please file an issue.
88 #[error("internal error: {0}")]
89 Internal(&'static str),
90}