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 "'{}' is a built-in pattern, it cannot be used as a custom pattern. try to replace it with `{{{}}}`",
109 placeholder, placeholder
110 )
111 } else {
112 write!(
113 f,
114 "'{}' is a custom pattern, it cannot be used as a built-in pattern. try to replace it with `{{${}}}`",
115 placeholder, placeholder
116 )
117 }
118 }
119 TemplateError::UnknownPatternReference {
120 is_custom,
121 placeholder,
122 } => {
123 if *is_custom {
124 write!(
125 f,
126 "the constructor of custom pattern '{}' is not specified",
127 placeholder
128 )
129 } else {
130 write!(f, "no built-in pattern named '{}'", placeholder)
131 }
132 }
133 TemplateError::MultipleStyleRange => {
134 write!(f, "multiple style ranges are not currently supported")
135 }
136 }
137 }
138}
139
140pub type Result<T> = std::result::Result<T, Error>;
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145
146 #[test]
147 fn push_err() {
148 macro_rules! make_err {
149 ( $($inputs:tt)+ ) => {
150 Error::__ForInternalTestsUseOnly($($inputs)*)
151 };
152 }
153
154 assert!(matches!(
155 Error::push_err(Ok(()), make_err!(1)),
156 Err(make_err!(1))
157 ));
158
159 assert!(matches!(
160 Error::push_err::<()>(Err(make_err!(1)), make_err!(2)),
161 Err(Error::Multiple(v)) if matches!(v[..], [make_err!(1), make_err!(2)])
162 ));
163 }
164}