spdlog_internal/pattern_parser/
error.rs1use std::fmt::{self, Display};
2
3use nom::error::Error as NomError;
4
5use super::PatternKind;
6use crate::impossible;
7
8#[derive(Debug, PartialEq)]
9pub enum Error {
10 ConflictName {
11 existing: PatternKind<()>,
12 incoming: PatternKind<()>,
13 },
14 Template(TemplateError),
15 Parse(NomError<String>),
16 Multiple(Vec<Error>),
17 #[cfg(test)]
18 __ForInternalTestsUseOnly(usize),
19}
20
21impl Error {
22 pub fn push_err<T>(result: Result<T>, new: Self) -> Result<T> {
23 match result {
24 Ok(_) => Err(new),
25 Err(Self::Multiple(mut errors)) => {
26 errors.push(new);
27 Err(Self::Multiple(errors))
28 }
29 Err(prev) => Err(Error::Multiple(vec![prev, new])),
30 }
31 }
32
33 pub fn push_result<T, N>(result: Result<T>, new: Result<N>) -> Result<T> {
34 match new {
35 Ok(_) => result,
36 Err(err) => Self::push_err(result, err),
37 }
38 }
39}
40
41impl Display for Error {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match self {
44 Error::ConflictName { existing, incoming } => match (existing, incoming) {
45 (PatternKind::BuiltIn(_), PatternKind::Custom { .. }) => {
46 write!(
47 f,
48 "'{}' is already a built-in pattern, please try another name",
49 existing.placeholder()
50 )
51 }
52 (PatternKind::Custom { .. }, PatternKind::Custom { .. }) => {
53 write!(
54 f,
55 "the constructor of custom pattern '{}' is specified more than once",
56 existing.placeholder()
57 )
58 }
59 (_, PatternKind::BuiltIn { .. }) => {
60 impossible!("{}", self)
61 }
62 },
63 Error::Template(err) => {
64 write!(f, "template ill-format: {err}")
65 }
66 Error::Parse(err) => {
67 write!(f, "failed to parse template string: {err}")
68 }
69 Error::Multiple(errs) => {
70 writeln!(f, "{} errors detected:", errs.len())?;
71 for err in errs {
72 writeln!(f, " - {err}")?;
73 }
74 Ok(())
75 }
76 #[cfg(test)]
77 Error::__ForInternalTestsUseOnly(value) => {
78 write!(f, "{value}")
79 }
80 }
81 }
82}
83
84#[derive(Debug, Eq, PartialEq)]
85pub enum TemplateError {
86 WrongPatternKindReference {
87 is_builtin_as_custom: bool,
88 placeholder: String,
89 },
90 UnknownPatternReference {
91 is_custom: bool,
92 placeholder: String,
93 },
94 MultipleStyleRange,
95}
96
97impl Display for TemplateError {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 match self {
100 TemplateError::WrongPatternKindReference {
101 is_builtin_as_custom,
102 placeholder,
103 } => {
104 if *is_builtin_as_custom {
105 write!(
106 f,
107 "'{placeholder}' is a built-in pattern, it cannot be used as a custom pattern. try to replace it with `{{{placeholder}}}`"
108 )
109 } else {
110 write!(
111 f,
112 "'{placeholder}' is a custom pattern, it cannot be used as a built-in pattern. try to replace it with `{{${placeholder}}}`"
113 )
114 }
115 }
116 TemplateError::UnknownPatternReference {
117 is_custom,
118 placeholder,
119 } => {
120 if *is_custom {
121 write!(
122 f,
123 "the constructor of custom pattern '{placeholder}' is not specified"
124 )
125 } else {
126 write!(f, "no built-in pattern named '{placeholder}'")
127 }
128 }
129 TemplateError::MultipleStyleRange => {
130 write!(f, "multiple style ranges are not currently supported")
131 }
132 }
133 }
134}
135
136pub type Result<T> = std::result::Result<T, Error>;
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn push_err() {
144 macro_rules! make_err {
145 ( $($inputs:tt)+ ) => {
146 Error::__ForInternalTestsUseOnly($($inputs)*)
147 };
148 }
149
150 assert!(matches!(
151 Error::push_err(Ok(()), make_err!(1)),
152 Err(make_err!(1))
153 ));
154
155 assert!(matches!(
156 Error::push_err::<()>(Err(make_err!(1)), make_err!(2)),
157 Err(Error::Multiple(v)) if matches!(v[..], [make_err!(1), make_err!(2)])
158 ));
159 }
160}