simple_html_template/
errors.rs1use std::error::Error as ErrorTrait;
2use std::fmt;
3
4#[derive(Clone, Debug, PartialEq, Eq, Hash)]
10pub struct Errors {
11 pub(crate) inner: Vec<Error>,
12}
13
14impl Errors {
15 pub fn into_inner(self) -> Vec<Error> {
17 self.inner
18 }
19}
20
21impl ErrorTrait for Errors {}
22
23impl fmt::Display for Errors {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 let uncloseds = self.inner.iter().filter_map(|e| {
27 if let Error::Unclosed(i) = e {
28 Some(i)
29 } else {
30 None
31 }
32 });
33
34 let missings = self.inner.iter().filter_map(|e| {
35 if let Error::Missing(k) = e {
36 Some(k)
37 } else {
38 None
39 }
40 });
41
42 let extras = self.inner.iter().filter_map(|e| {
43 if let Error::Extra(k) = e {
44 Some(k)
45 } else {
46 None
47 }
48 });
49
50 let uncloseds_count = uncloseds.clone().count();
51 let missings_count = missings.clone().count();
52 let extras_count = extras.clone().count();
53
54 format_error(
55 f,
56 "unclosed delimiter opened at byte",
57 uncloseds,
58 uncloseds_count,
59 false,
60 )?;
61
62 if uncloseds_count > 0 && missings_count > 0 {
63 write!(f, "; ")?;
64 }
65
66 format_error(f, "missing key", missings, missings_count, true)?;
67
68 if (uncloseds_count > 0 || missings_count > 0) && extras_count > 0 {
69 write!(f, "; ")?;
70 }
71
72 format_error(f, "extraneous key", extras, extras_count, true)?;
73
74 Ok(())
75 }
76}
77
78fn format_error(
80 f: &mut fmt::Formatter<'_>,
81 problem: &str,
82 iter: impl Iterator<Item = impl fmt::Display>,
83 count: usize,
84 quotes: bool,
85) -> fmt::Result {
86 if count > 0 {
87 let s = if count != 1 {
88 "s"
89 } else {
90 ""
91 };
92
93 write!(f, "{}{}: ", problem, s)?;
94 for (i, error) in iter.enumerate() {
95 let sep = if i + 1 == count {
96 ""
97 } else if i + 2 == count {
98 if count == 2 {
99 " and "
100 } else {
101 ", and "
102 }
103 } else {
104 ", "
105 };
106
107 if quotes {
108 write!(f, "\"{}\"{}", error, sep)?;
109 } else {
110 write!(f, "{}{}", error, sep)?;
111 }
112 }
113 }
114
115 Ok(())
116}
117
118#[derive(Clone, Debug, PartialEq, Eq, Hash)]
120pub enum Error {
121 Missing(String),
125
126 Extra(String),
130
131 Unclosed(usize),
137}
138
139impl fmt::Display for Error {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 match self {
142 Self::Missing(k) => write!(f, "missing key \"{}\"", k),
143 Self::Extra(k) => write!(f, "extraneous key \"{}\"", k),
144 Self::Unclosed(i) => {
145 write!(f, "unclosed delimitor opened at byte {}", i)
146 }
147 }
148 }
149}