muffy_validation/
error.rs1use alloc::collections::{BTreeMap, BTreeSet};
2use core::fmt::{self, Display, Formatter};
3
4#[derive(Clone, Debug, Eq, PartialEq)]
6pub enum ValidationError {
7 UnknownTag(String),
9 InvalidElement {
11 attributes: BTreeMap<String, BTreeSet<AttributeError>>,
13 children: BTreeMap<String, BTreeSet<ChildError>>,
15 },
16}
17
18impl Display for ValidationError {
19 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
20 match self {
21 Self::UnknownTag(tag) => write!(formatter, "unknown tag \"{tag}\""),
22 Self::InvalidElement {
23 attributes,
24 children,
25 } => {
26 if !attributes.is_empty() {
27 write!(formatter, "invalid attributes: ")?;
28
29 for (index, (name, errors)) in attributes.iter().enumerate() {
30 if index > 0 {
31 write!(formatter, ", ")?;
32 }
33
34 write!(formatter, "{name} (")?;
35
36 for (index, error) in errors.iter().enumerate() {
37 if index > 0 {
38 write!(formatter, ", ")?;
39 }
40
41 write!(formatter, "{error}")?;
42 }
43
44 write!(formatter, ")")?;
45 }
46 }
47
48 if !children.is_empty() {
49 if !attributes.is_empty() {
50 write!(formatter, ", ")?;
51 }
52
53 write!(formatter, "invalid children: ")?;
54
55 for (index, (name, errors)) in children.iter().enumerate() {
56 if index > 0 {
57 write!(formatter, ", ")?;
58 }
59
60 write!(formatter, "{name} (")?;
61
62 for (index, error) in errors.iter().enumerate() {
63 if index > 0 {
64 write!(formatter, ", ")?;
65 }
66
67 write!(formatter, "{error}")?;
68 }
69
70 write!(formatter, ")")?;
71 }
72 }
73
74 Ok(())
75 }
76 }
77 }
78}
79
80#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
82pub enum AttributeError {
83 NotAllowed,
85}
86
87impl Display for AttributeError {
88 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
89 match self {
90 Self::NotAllowed => write!(formatter, "not allowed"),
91 }
92 }
93}
94
95#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
97pub enum ChildError {
98 NotAllowed,
100}
101
102impl Display for ChildError {
103 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
104 match self {
105 Self::NotAllowed => write!(formatter, "not allowed"),
106 }
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn display_unknown_tag() {
116 assert_eq!(
117 format!("{}", ValidationError::UnknownTag("foo".into())),
118 "unknown tag \"foo\""
119 );
120 }
121
122 #[test]
123 fn display_not_allowed_attributes() {
124 assert_eq!(
125 format!(
126 "{}",
127 ValidationError::InvalidElement {
128 attributes: [("foo".into(), [AttributeError::NotAllowed].into())].into(),
129 children: Default::default(),
130 }
131 ),
132 "invalid attributes: foo (not allowed)"
133 );
134 }
135
136 #[test]
137 fn display_not_allowed_children() {
138 assert_eq!(
139 format!(
140 "{}",
141 ValidationError::InvalidElement {
142 attributes: Default::default(),
143 children: [("foo".into(), [ChildError::NotAllowed].into())].into(),
144 }
145 ),
146 "invalid children: foo (not allowed)"
147 );
148 }
149
150 #[test]
151 fn display_not_allowed_attributes_and_children() {
152 assert_eq!(
153 format!(
154 "{}",
155 ValidationError::InvalidElement {
156 attributes: [("foo".into(), [AttributeError::NotAllowed].into())].into(),
157 children: [("bar".into(), [ChildError::NotAllowed].into())].into(),
158 }
159 ),
160 "invalid attributes: foo (not allowed), invalid children: bar (not allowed)"
161 );
162 }
163}