1macro_rules! get_attr {
8 ($elem:ident, $attr:tt, $type:tt) => {
9 get_attr!(
10 $elem,
11 $attr,
12 $type,
13 value,
14 value.parse().map_err(xso::error::Error::text_parse_error)?
15 )
16 };
17 ($elem:ident, $attr:tt, Option, $value:ident, $func:expr) => {
18 match $elem.attr($attr) {
19 Some($value) => Some($func),
20 None => None,
21 }
22 };
23 ($elem:ident, $attr:tt, Required, $value:ident, $func:expr) => {
24 match $elem.attr($attr) {
25 Some($value) => $func,
26 None => {
27 return Err(xso::error::Error::Other(
28 concat!("Required attribute '", $attr, "' missing.").into(),
29 )
30 .into());
31 }
32 }
33 };
34 ($elem:ident, $attr:tt, Default, $value:ident, $func:expr) => {
35 match $elem.attr($attr) {
36 Some($value) => $func,
37 None => ::core::default::Default::default(),
38 }
39 };
40}
41
42macro_rules! generate_attribute {
43 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+$(,)?}) => (
44 $(#[$meta])*
45 #[derive(Debug, Clone, PartialEq)]
46 pub enum $elem {
47 $(
48 $(#[$a_meta])*
49 $a
50 ),+
51 }
52 impl ::core::str::FromStr for $elem {
53 type Err = xso::error::Error;
54 fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
55 Ok(match s {
56 $($b => $elem::$a),+,
57 _ => return Err(xso::error::Error::Other(concat!("Unknown value for '", $name, "' attribute.")).into()),
58 })
59 }
60 }
61 impl ::xso::FromXmlText for $elem {
62 fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
63 s.parse().map_err(xso::error::Error::text_parse_error)
64 }
65 }
66 impl core::fmt::Display for $elem {
67 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
68 write!(fmt, "{}", match self {
69 $($elem::$a => $b),+
70 })
71 }
72 }
73 impl ::xso::AsXmlText for $elem {
74 fn as_xml_text(&self) -> Result<::alloc::borrow::Cow<'_, str>, xso::error::Error> {
75 match self {
76 $(
77 $elem::$a => Ok(::alloc::borrow::Cow::Borrowed($b))
78 ),+
79 }
80 }
81 }
82 impl ::minidom::IntoAttributeValue for $elem {
83 fn into_attribute_value(self) -> Option<String> {
84 Some(String::from(match self {
85 $($elem::$a => $b),+
86 }))
87 }
88 }
89 );
90 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+$(,)?}, Default = $default:ident) => (
91 $(#[$meta])*
92 #[derive(Debug, Clone, PartialEq)]
93 pub enum $elem {
94 $(
95 $(#[$a_meta])*
96 $a
97 ),+
98 }
99 impl ::core::str::FromStr for $elem {
100 type Err = xso::error::Error;
101 fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
102 Ok(match s {
103 $($b => $elem::$a),+,
104 _ => return Err(xso::error::Error::Other(concat!("Unknown value for '", $name, "' attribute.")).into()),
105 })
106 }
107 }
108 impl ::xso::FromXmlText for $elem {
109 fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
110 s.parse().map_err(xso::error::Error::text_parse_error)
111 }
112 }
113 impl ::xso::AsXmlText for $elem {
114 fn as_xml_text(&self) -> Result<alloc::borrow::Cow<'_, str>, xso::error::Error> {
115 Ok(alloc::borrow::Cow::Borrowed(match self {
116 $($elem::$a => $b),+
117 }))
118 }
119
120 #[allow(unreachable_patterns)]
121 fn as_optional_xml_text(&self) -> Result<Option<alloc::borrow::Cow<'_, str>>, xso::error::Error> {
122 Ok(Some(alloc::borrow::Cow::Borrowed(match self {
123 $elem::$default => return Ok(None),
124 $($elem::$a => $b),+
125 })))
126 }
127 }
128 impl ::minidom::IntoAttributeValue for $elem {
129 #[allow(unreachable_patterns)]
130 fn into_attribute_value(self) -> Option<String> {
131 Some(String::from(match self {
132 $elem::$default => return None,
133 $($elem::$a => $b),+
134 }))
135 }
136 }
137 impl ::core::default::Default for $elem {
138 fn default() -> $elem {
139 $elem::$default
140 }
141 }
142 );
143 ($(#[$meta:meta])* $elem:ident, $name:tt, ($(#[$meta_symbol:meta])* $symbol:ident => $value:tt)) => (
144 $(#[$meta])*
145 #[derive(Debug, Clone, PartialEq)]
146 pub enum $elem {
147 $(#[$meta_symbol])*
148 $symbol,
149 None,
151 }
152 impl ::core::str::FromStr for $elem {
153 type Err = xso::error::Error;
154 fn from_str(s: &str) -> Result<Self, xso::error::Error> {
155 Ok(match s {
156 $value => $elem::$symbol,
157 _ => return Err(xso::error::Error::Other(concat!("Unknown value for '", $name, "' attribute."))),
158 })
159 }
160 }
161 impl ::minidom::IntoAttributeValue for $elem {
162 fn into_attribute_value(self) -> Option<String> {
163 match self {
164 $elem::$symbol => Some(String::from($value)),
165 $elem::None => None
166 }
167 }
168 }
169 impl ::core::default::Default for $elem {
170 fn default() -> $elem {
171 $elem::None
172 }
173 }
174 impl ::xso::FromXmlText for $elem {
175 fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
176 s.parse().map_err(xso::error::Error::text_parse_error)
177 }
178 }
179 impl ::xso::AsXmlText for $elem {
180 fn as_xml_text(&self) -> Result<::alloc::borrow::Cow<'_, str>, xso::error::Error> {
181 Ok(::alloc::borrow::Cow::Borrowed($value))
182 }
183
184 #[allow(unreachable_patterns)]
185 fn as_optional_xml_text(&self) -> Result<Option<alloc::borrow::Cow<'_, str>>, xso::error::Error> {
186 Ok(Some(alloc::borrow::Cow::Borrowed(match self {
187 $elem::$symbol => $value,
188 $elem::None => return Ok(None),
189 })))
190 }
191 }
192 );
193 ($(#[$meta:meta])* $elem:ident, $name:tt, $type:tt, Default = $default:expr) => (
194 $(#[$meta])*
195 #[derive(Debug, Clone, PartialEq)]
196 pub struct $elem(pub $type);
197 impl ::core::str::FromStr for $elem {
198 type Err = xso::error::Error;
199 fn from_str(s: &str) -> Result<Self, xso::error::Error> {
200 Ok($elem($type::from_str(s).map_err(xso::error::Error::text_parse_error)?))
201 }
202 }
203 impl ::minidom::IntoAttributeValue for $elem {
204 fn into_attribute_value(self) -> Option<String> {
205 match self {
206 $elem($default) => None,
207 $elem(value) => Some(format!("{}", value)),
208 }
209 }
210 }
211 impl ::core::default::Default for $elem {
212 fn default() -> $elem {
213 $elem($default)
214 }
215 }
216 impl ::xso::FromXmlText for $elem {
217 fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
218 s.parse().map_err(xso::error::Error::text_parse_error)
219 }
220 }
221 impl ::xso::AsXmlText for $elem {
222 fn as_xml_text(&self) -> Result<::alloc::borrow::Cow<'_, str>, xso::error::Error> {
223 Ok(::alloc::borrow::Cow::Owned(format!("{}", self.0)))
224 }
225
226 fn as_optional_xml_text(&self) -> Result<Option<::alloc::borrow::Cow<'_, str>>, xso::error::Error> {
227 match self.0 {
228 $default => Ok(None),
229 _ => Ok(Some(::alloc::borrow::Cow::Owned(format!("{}", self.0)))),
230 }
231 }
232 }
233 );
234}
235
236macro_rules! generate_attribute_enum {
237 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $attr:tt, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+$(,)?}) => (
238 $(#[$meta])*
239 #[derive(Debug, Clone, PartialEq)]
240 pub enum $elem {
241 $(
242 $(#[$enum_meta])*
243 $enum
244 ),+
245 }
246 impl ::core::convert::TryFrom<minidom::Element> for $elem {
247 type Error = xso::error::FromElementError;
248 fn try_from(elem: minidom::Element) -> Result<$elem, xso::error::FromElementError> {
249 check_ns_only!(elem, $name, $ns);
250 check_no_children!(elem, $name);
251 check_no_unknown_attributes!(elem, $name, [$attr]);
252 Ok(match get_attr!(elem, $attr, Required) {
253 $($enum_name => $elem::$enum,)+
254 _ => return Err(xso::error::Error::Other(concat!("Invalid ", $name, " ", $attr, " value.")).into()),
255 })
256 }
257 }
258
259 impl ::xso::FromXml for $elem {
260 type Builder = ::xso::minidom_compat::FromEventsViaElement<$elem>;
261
262 fn from_events(
263 qname: ::xso::exports::rxml::QName,
264 attrs: ::xso::exports::rxml::AttrMap,
265 ) -> Result<Self::Builder, ::xso::error::FromEventsError> {
266 if qname.0 != crate::ns::$ns || qname.1 != $name {
267 return Err(::xso::error::FromEventsError::Mismatch {
268 name: qname,
269 attrs,
270 })
271 }
272 Self::Builder::new(qname, attrs)
273 }
274 }
275
276 impl From<$elem> for minidom::Element {
277 fn from(elem: $elem) -> minidom::Element {
278 minidom::Element::builder($name, crate::ns::$ns)
279 .attr($attr, match elem {
280 $($elem::$enum => $enum_name,)+
281 })
282 .build()
283 }
284 }
285
286 impl ::xso::AsXml for $elem {
287 type ItemIter<'x> = ::xso::minidom_compat::AsItemsViaElement<'x>;
288
289 fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, ::xso::error::Error> {
290 ::xso::minidom_compat::AsItemsViaElement::new(self.clone())
291 }
292 }
293 );
294}
295
296macro_rules! check_self {
297 ($elem:ident, $name:tt, $ns:ident) => {
298 check_self!($elem, $name, $ns, $name);
299 };
300 ($elem:ident, $name:tt, $ns:ident, $pretty_name:tt) => {
301 if !$elem.is($name, crate::ns::$ns) {
302 return Err(xso::error::FromElementError::Mismatch($elem));
303 }
304 };
305}
306
307macro_rules! check_ns_only {
308 ($elem:ident, $name:tt, $ns:ident) => {
309 if !$elem.has_ns(crate::ns::$ns) {
310 return Err(xso::error::Error::Other(
311 concat!("This is not a ", $name, " element.").into(),
312 )
313 .into());
314 }
315 };
316}
317
318macro_rules! check_no_children {
319 ($elem:ident, $name:tt) => {
320 #[cfg(not(feature = "disable-validation"))]
321 for _ in $elem.children() {
322 return Err(xso::error::Error::Other(
323 concat!("Unknown child in ", $name, " element.").into(),
324 )
325 .into());
326 }
327 };
328}
329
330macro_rules! check_no_attributes {
331 ($elem:ident, $name:tt) => {
332 #[cfg(not(feature = "disable-validation"))]
333 for _ in $elem.attrs() {
334 return Err(xso::error::Error::Other(
335 concat!("Unknown attribute in ", $name, " element.").into(),
336 )
337 .into());
338 }
339 };
340}
341
342macro_rules! check_no_unknown_attributes {
343 ($elem:ident, $name:tt, [$($attr:tt),*]) => (
344 #[cfg(not(feature = "disable-validation"))]
345 for (_attr, _) in $elem.attrs() {
346 $(
347 if _attr == $attr {
348 continue;
349 }
350 )*
351 return Err(xso::error::Error::Other(concat!("Unknown attribute in ", $name, " element.")).into());
352 }
353 );
354}
355
356macro_rules! generate_id {
357 ($(#[$meta:meta])* $elem:ident) => (
358 $(#[$meta])*
359 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
360 pub struct $elem(pub String);
361 impl ::core::str::FromStr for $elem {
362 type Err = xso::error::Error;
363 fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
364 Ok($elem(String::from(s)))
366 }
367 }
368 impl ::xso::FromXmlText for $elem {
369 fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
370 Ok(Self(s))
371 }
372 }
373 impl ::xso::AsXmlText for $elem {
374 fn as_xml_text(&self) ->Result<::alloc::borrow::Cow<'_, str>, xso::error::Error> {
375 Ok(::alloc::borrow::Cow::Borrowed(self.0.as_str()))
376 }
377 }
378 impl ::minidom::IntoAttributeValue for $elem {
379 fn into_attribute_value(self) -> Option<String> {
380 Some(self.0)
381 }
382 }
383 );
384}
385
386macro_rules! generate_elem_id {
387 ($(#[$meta:meta])* $elem:ident, $name:literal, $ns:ident) => (
388 generate_elem_id!($(#[$meta])* $elem, $name, $ns, String);
389 impl ::core::str::FromStr for $elem {
390 type Err = xso::error::Error;
391 fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
392 Ok($elem(String::from(s)))
394 }
395 }
396 );
397 ($(#[$meta:meta])* $elem:ident, $name:literal, $ns:ident, $type:ty) => (
398 $(#[$meta])*
399 #[derive(xso::FromXml, xso::AsXml, Debug, Clone, PartialEq, Eq, Hash)]
400 #[xml(namespace = crate::ns::$ns, name = $name)]
401 pub struct $elem(#[xml(text)] pub $type);
402 );
403}
404
405#[cfg(test)]
406macro_rules! assert_size (
407 ($t:ty, $sz:expr) => (
408 assert_eq!(::core::mem::size_of::<$t>(), $sz);
409 );
410);