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