1// Copyright (c) 2017-2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7macro_rules! get_attr {
8 ($elem:ident, $attr:tt, $type:tt) => {
9 get_attr!($elem, $attr, $type, value, value.parse()?)
10 };
11 ($elem:ident, $attr:tt, OptionEmpty, $value:ident, $func:expr) => {
12 match $elem.attr($attr) {
13 Some("") => None,
14 Some($value) => Some($func),
15 None => None,
16 }
17 };
18 ($elem:ident, $attr:tt, Option, $value:ident, $func:expr) => {
19 match $elem.attr($attr) {
20 Some($value) => Some($func),
21 None => None,
22 }
23 };
24 ($elem:ident, $attr:tt, Required, $value:ident, $func:expr) => {
25 match $elem.attr($attr) {
26 Some($value) => $func,
27 None => {
28 return Err(crate::util::error::Error::ParseError(concat!(
29 "Required attribute '",
30 $attr,
31 "' missing."
32 )));
33 }
34 }
35 };
36 ($elem:ident, $attr:tt, Default, $value:ident, $func:expr) => {
37 match $elem.attr($attr) {
38 Some($value) => $func,
39 None => ::std::default::Default::default(),
40 }
41 };
42}
43
44macro_rules! generate_attribute {
45 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+,}) => (
46 generate_attribute!($(#[$meta])* $elem, $name, {$($(#[$a_meta])* $a => $b),+});
47 );
48 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+,}, Default = $default:ident) => (
49 generate_attribute!($(#[$meta])* $elem, $name, {$($(#[$a_meta])* $a => $b),+}, Default = $default);
50 );
51 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+}) => (
52 $(#[$meta])*
53 #[derive(Debug, Clone, PartialEq)]
54 pub enum $elem {
55 $(
56 $(#[$a_meta])*
57 $a
58 ),+
59 }
60 impl ::std::str::FromStr for $elem {
61 type Err = crate::util::error::Error;
62 fn from_str(s: &str) -> Result<$elem, crate::util::error::Error> {
63 Ok(match s {
64 $($b => $elem::$a),+,
65 _ => return Err(crate::util::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
66 })
67 }
68 }
69 impl ::minidom::IntoAttributeValue for $elem {
70 fn into_attribute_value(self) -> Option<String> {
71 Some(String::from(match self {
72 $($elem::$a => $b),+
73 }))
74 }
75 }
76 );
77 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+}, Default = $default:ident) => (
78 $(#[$meta])*
79 #[derive(Debug, Clone, PartialEq)]
80 pub enum $elem {
81 $(
82 $(#[$a_meta])*
83 $a
84 ),+
85 }
86 impl ::std::str::FromStr for $elem {
87 type Err = crate::util::error::Error;
88 fn from_str(s: &str) -> Result<$elem, crate::util::error::Error> {
89 Ok(match s {
90 $($b => $elem::$a),+,
91 _ => return Err(crate::util::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
92 })
93 }
94 }
95 impl ::minidom::IntoAttributeValue for $elem {
96 #[allow(unreachable_patterns)]
97 fn into_attribute_value(self) -> Option<String> {
98 Some(String::from(match self {
99 $elem::$default => return None,
100 $($elem::$a => $b),+
101 }))
102 }
103 }
104 impl ::std::default::Default for $elem {
105 fn default() -> $elem {
106 $elem::$default
107 }
108 }
109 );
110 ($(#[$meta:meta])* $elem:ident, $name:tt, ($(#[$meta_symbol:meta])* $symbol:ident => $value:tt)) => (
111 $(#[$meta])*
112 #[derive(Debug, Clone, PartialEq)]
113 pub enum $elem {
114 $(#[$meta_symbol])*
115 $symbol,
116 /// Value when absent.
117 None,
118 }
119 impl ::std::str::FromStr for $elem {
120 type Err = crate::util::error::Error;
121 fn from_str(s: &str) -> Result<Self, crate::util::error::Error> {
122 Ok(match s {
123 $value => $elem::$symbol,
124 _ => return Err(crate::util::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
125 })
126 }
127 }
128 impl ::minidom::IntoAttributeValue for $elem {
129 fn into_attribute_value(self) -> Option<String> {
130 match self {
131 $elem::$symbol => Some(String::from($value)),
132 $elem::None => None
133 }
134 }
135 }
136 impl ::std::default::Default for $elem {
137 fn default() -> $elem {
138 $elem::None
139 }
140 }
141 );
142 ($(#[$meta:meta])* $elem:ident, $name:tt, bool) => (
143 $(#[$meta])*
144 #[derive(Debug, Clone, PartialEq)]
145 pub enum $elem {
146 /// True value, represented by either 'true' or '1'.
147 True,
148 /// False value, represented by either 'false' or '0'.
149 False,
150 }
151 impl ::std::str::FromStr for $elem {
152 type Err = crate::util::error::Error;
153 fn from_str(s: &str) -> Result<Self, crate::util::error::Error> {
154 Ok(match s {
155 "true" | "1" => $elem::True,
156 "false" | "0" => $elem::False,
157 _ => return Err(crate::util::error::Error::ParseError(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::True => Some(String::from("true")),
165 $elem::False => None
166 }
167 }
168 }
169 impl ::std::default::Default for $elem {
170 fn default() -> $elem {
171 $elem::False
172 }
173 }
174 );
175}
176
177macro_rules! generate_element_enum {
178 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+,}) => (
179 generate_element_enum!($(#[$meta])* $elem, $name, $ns, {$($(#[$enum_meta])* $enum => $enum_name),+});
180 );
181 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+}) => (
182 $(#[$meta])*
183 #[derive(Debug, Clone, PartialEq)]
184 pub enum $elem {
185 $(
186 $(#[$enum_meta])*
187 $enum
188 ),+
189 }
190 impl ::try_from::TryFrom<::minidom::Element> for $elem {
191 type Err = crate::util::error::Error;
192 fn try_from(elem: ::minidom::Element) -> Result<$elem, crate::util::error::Error> {
193 check_ns_only!(elem, $name, $ns);
194 check_no_children!(elem, $name);
195 check_no_attributes!(elem, $name);
196 Ok(match elem.name() {
197 $($enum_name => $elem::$enum,)+
198 _ => return Err(crate::util::error::Error::ParseError(concat!("This is not a ", $name, " element."))),
199 })
200 }
201 }
202 impl From<$elem> for ::minidom::Element {
203 fn from(elem: $elem) -> ::minidom::Element {
204 ::minidom::Element::builder(
205 match elem {
206 $($elem::$enum => $enum_name,)+
207 }
208 )
209 .ns(crate::ns::$ns)
210 .build()
211 }
212 }
213 );
214}
215
216macro_rules! generate_attribute_enum {
217 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $attr:tt, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+,}) => (
218 generate_attribute_enum!($(#[$meta])* $elem, $name, $ns, $attr, {$($(#[$enum_meta])* $enum => $enum_name),+});
219 );
220 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $attr:tt, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+}) => (
221 $(#[$meta])*
222 #[derive(Debug, Clone, PartialEq)]
223 pub enum $elem {
224 $(
225 $(#[$enum_meta])*
226 $enum
227 ),+
228 }
229 impl ::try_from::TryFrom<::minidom::Element> for $elem {
230 type Err = crate::util::error::Error;
231 fn try_from(elem: ::minidom::Element) -> Result<$elem, crate::util::error::Error> {
232 check_ns_only!(elem, $name, $ns);
233 check_no_children!(elem, $name);
234 check_no_unknown_attributes!(elem, $name, [$attr]);
235 Ok(match get_attr!(elem, $attr, Required) {
236 $($enum_name => $elem::$enum,)+
237 _ => return Err(crate::util::error::Error::ParseError(concat!("Invalid ", $name, " ", $attr, " value."))),
238 })
239 }
240 }
241 impl From<$elem> for ::minidom::Element {
242 fn from(elem: $elem) -> ::minidom::Element {
243 ::minidom::Element::builder($name)
244 .ns(crate::ns::$ns)
245 .attr($attr, match elem {
246 $($elem::$enum => $enum_name,)+
247 })
248 .build()
249 }
250 }
251 );
252}
253
254macro_rules! check_self {
255 ($elem:ident, $name:tt, $ns:ident) => {
256 check_self!($elem, $name, $ns, $name);
257 };
258 ($elem:ident, $name:tt, $ns:ident, $pretty_name:tt) => {
259 if !$elem.is($name, crate::ns::$ns) {
260 return Err(crate::util::error::Error::ParseError(concat!(
261 "This is not a ",
262 $pretty_name,
263 " element."
264 )));
265 }
266 };
267}
268
269macro_rules! check_ns_only {
270 ($elem:ident, $name:tt, $ns:ident) => {
271 if !$elem.has_ns(crate::ns::$ns) {
272 return Err(crate::util::error::Error::ParseError(concat!(
273 "This is not a ",
274 $name,
275 " element."
276 )));
277 }
278 };
279}
280
281macro_rules! check_no_children {
282 ($elem:ident, $name:tt) => {
283 #[cfg(not(feature = "disable-validation"))]
284 for _ in $elem.children() {
285 return Err(crate::util::error::Error::ParseError(concat!(
286 "Unknown child in ",
287 $name,
288 " element."
289 )));
290 }
291 };
292}
293
294macro_rules! check_no_attributes {
295 ($elem:ident, $name:tt) => {
296 #[cfg(not(feature = "disable-validation"))]
297 for _ in $elem.attrs() {
298 return Err(crate::util::error::Error::ParseError(concat!(
299 "Unknown attribute in ",
300 $name,
301 " element."
302 )));
303 }
304 };
305}
306
307macro_rules! check_no_unknown_attributes {
308 ($elem:ident, $name:tt, [$($attr:tt),*]) => (
309 #[cfg(not(feature = "disable-validation"))]
310 for (_attr, _) in $elem.attrs() {
311 $(
312 if _attr == $attr {
313 continue;
314 }
315 )*
316 return Err(crate::util::error::Error::ParseError(concat!("Unknown attribute in ", $name, " element.")));
317 }
318 );
319}
320
321macro_rules! generate_empty_element {
322 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident) => (
323 $(#[$meta])*
324 #[derive(Debug, Clone)]
325 pub struct $elem;
326
327 impl ::try_from::TryFrom<::minidom::Element> for $elem {
328 type Err = crate::util::error::Error;
329
330 fn try_from(elem: ::minidom::Element) -> Result<$elem, crate::util::error::Error> {
331 check_self!(elem, $name, $ns);
332 check_no_children!(elem, $name);
333 check_no_attributes!(elem, $name);
334 Ok($elem)
335 }
336 }
337
338 impl From<$elem> for ::minidom::Element {
339 fn from(_: $elem) -> ::minidom::Element {
340 ::minidom::Element::builder($name)
341 .ns(crate::ns::$ns)
342 .build()
343 }
344 }
345 );
346}
347
348macro_rules! generate_id {
349 ($(#[$meta:meta])* $elem:ident) => (
350 $(#[$meta])*
351 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
352 pub struct $elem(pub String);
353 impl ::std::str::FromStr for $elem {
354 type Err = crate::util::error::Error;
355 fn from_str(s: &str) -> Result<$elem, crate::util::error::Error> {
356 // TODO: add a way to parse that differently when needed.
357 Ok($elem(String::from(s)))
358 }
359 }
360 impl ::minidom::IntoAttributeValue for $elem {
361 fn into_attribute_value(self) -> Option<String> {
362 Some(self.0)
363 }
364 }
365 );
366}
367
368macro_rules! generate_elem_id {
369 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident) => (
370 $(#[$meta])*
371 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
372 pub struct $elem(pub String);
373 impl ::std::str::FromStr for $elem {
374 type Err = crate::util::error::Error;
375 fn from_str(s: &str) -> Result<$elem, crate::util::error::Error> {
376 // TODO: add a way to parse that differently when needed.
377 Ok($elem(String::from(s)))
378 }
379 }
380 impl ::try_from::TryFrom<::minidom::Element> for $elem {
381 type Err = crate::util::error::Error;
382 fn try_from(elem: ::minidom::Element) -> Result<$elem, crate::util::error::Error> {
383 check_self!(elem, $name, $ns);
384 check_no_children!(elem, $name);
385 check_no_attributes!(elem, $name);
386 // TODO: add a way to parse that differently when needed.
387 Ok($elem(elem.text()))
388 }
389 }
390 impl From<$elem> for ::minidom::Element {
391 fn from(elem: $elem) -> ::minidom::Element {
392 ::minidom::Element::builder($name)
393 .ns(crate::ns::$ns)
394 .append(elem.0)
395 .build()
396 }
397 }
398 );
399}
400
401macro_rules! decl_attr {
402 (OptionEmpty, $type:ty) => (
403 Option<$type>
404 );
405 (Option, $type:ty) => (
406 Option<$type>
407 );
408 (Required, $type:ty) => (
409 $type
410 );
411 (Default, $type:ty) => (
412 $type
413 );
414}
415
416macro_rules! start_decl {
417 (Vec, $type:ty) => (
418 Vec<$type>
419 );
420 (Option, $type:ty) => (
421 Option<$type>
422 );
423 (Required, $type:ty) => (
424 $type
425 );
426}
427
428macro_rules! start_parse_elem {
429 ($temp:ident: Vec) => {
430 let mut $temp = Vec::new();
431 };
432 ($temp:ident: Option) => {
433 let mut $temp = None;
434 };
435 ($temp:ident: Required) => {
436 let mut $temp = None;
437 };
438}
439
440macro_rules! do_parse {
441 ($elem:ident, Element) => {
442 $elem.clone()
443 };
444 ($elem:ident, String) => {
445 $elem.text()
446 };
447 ($elem:ident, $constructor:ident) => {
448 $constructor::try_from($elem.clone())?
449 };
450}
451
452macro_rules! do_parse_elem {
453 ($temp:ident: Vec = $constructor:ident => $elem:ident, $name:tt, $parent_name:tt) => {
454 $temp.push(do_parse!($elem, $constructor));
455 };
456 ($temp:ident: Option = $constructor:ident => $elem:ident, $name:tt, $parent_name:tt) => {
457 if $temp.is_some() {
458 return Err(crate::util::error::Error::ParseError(concat!(
459 "Element ",
460 $parent_name,
461 " must not have more than one ",
462 $name,
463 " child."
464 )));
465 }
466 $temp = Some(do_parse!($elem, $constructor));
467 };
468 ($temp:ident: Required = $constructor:ident => $elem:ident, $name:tt, $parent_name:tt) => {
469 if $temp.is_some() {
470 return Err(crate::util::error::Error::ParseError(concat!(
471 "Element ",
472 $parent_name,
473 " must not have more than one ",
474 $name,
475 " child."
476 )));
477 }
478 $temp = Some(do_parse!($elem, $constructor));
479 };
480}
481
482macro_rules! finish_parse_elem {
483 ($temp:ident: Vec = $name:tt, $parent_name:tt) => {
484 $temp
485 };
486 ($temp:ident: Option = $name:tt, $parent_name:tt) => {
487 $temp
488 };
489 ($temp:ident: Required = $name:tt, $parent_name:tt) => {
490 $temp.ok_or(crate::util::error::Error::ParseError(concat!(
491 "Missing child ",
492 $name,
493 " in ",
494 $parent_name,
495 " element."
496 )))?
497 };
498}
499
500macro_rules! generate_serialiser {
501 ($parent:ident, $elem:ident, Required, String, ($name:tt, $ns:ident)) => {
502 ::minidom::Element::builder($name)
503 .ns(crate::ns::$ns)
504 .append($parent.$elem)
505 .build()
506 };
507 ($parent:ident, $elem:ident, Option, String, ($name:tt, $ns:ident)) => {
508 $parent.$elem.map(|elem| {
509 ::minidom::Element::builder($name)
510 .ns(crate::ns::$ns)
511 .append(elem)
512 .build()
513 })
514 };
515 ($parent:ident, $elem:ident, $_:ident, $constructor:ident, ($name:tt, $ns:ident)) => {
516 $parent.$elem
517 };
518}
519
520macro_rules! generate_element {
521 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_action:tt<$attr_type:ty> = $attr_name:tt),+,]) => (
522 generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_action<$attr_type> = $attr_name),*], children: []);
523 );
524 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_action:tt<$attr_type:ty> = $attr_name:tt),+]) => (
525 generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_action<$attr_type> = $attr_name),*], children: []);
526 );
527 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, children: [$($(#[$child_meta:meta])* $child_ident:ident: $coucou:tt<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),*]) => (
528 generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [], children: [$($(#[$child_meta])* $child_ident: $coucou<$child_type> = ($child_name, $child_ns) => $child_constructor),*]);
529 );
530 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_action:tt<$attr_type:ty> = $attr_name:tt),*,], children: [$($(#[$child_meta:meta])* $child_ident:ident: $coucou:tt<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),*]) => (
531 generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_action<$attr_type> = $attr_name),*], children: [$($(#[$child_meta])* $child_ident: $coucou<$child_type> = ($child_name, $child_ns) => $child_constructor),*]);
532 );
533 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, text: ($(#[$text_meta:meta])* $text_ident:ident: $codec:ident < $text_type:ty >)) => (
534 generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [], children: [], text: ($(#[$text_meta])* $text_ident: $codec<$text_type>));
535 );
536 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_action:tt<$attr_type:ty> = $attr_name:tt),+], text: ($(#[$text_meta:meta])* $text_ident:ident: $codec:ident < $text_type:ty >)) => (
537 generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_action<$attr_type> = $attr_name),*], children: [], text: ($(#[$text_meta])* $text_ident: $codec<$text_type>));
538 );
539 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_action:tt<$attr_type:ty> = $attr_name:tt),*], children: [$($(#[$child_meta:meta])* $child_ident:ident: $coucou:tt<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),*] $(, text: ($(#[$text_meta:meta])* $text_ident:ident: $codec:ident < $text_type:ty >))*) => (
540 $(#[$meta])*
541 #[derive(Debug, Clone)]
542 pub struct $elem {
543 $(
544 $(#[$attr_meta])*
545 pub $attr: decl_attr!($attr_action, $attr_type),
546 )*
547 $(
548 $(#[$child_meta])*
549 pub $child_ident: start_decl!($coucou, $child_type),
550 )*
551 $(
552 $(#[$text_meta])*
553 pub $text_ident: $text_type,
554 )*
555 }
556
557 impl ::try_from::TryFrom<::minidom::Element> for $elem {
558 type Err = crate::util::error::Error;
559
560 fn try_from(elem: ::minidom::Element) -> Result<$elem, crate::util::error::Error> {
561 check_self!(elem, $name, $ns);
562 check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
563 $(
564 start_parse_elem!($child_ident: $coucou);
565 )*
566 for _child in elem.children() {
567 $(
568 if _child.is($child_name, crate::ns::$child_ns) {
569 do_parse_elem!($child_ident: $coucou = $child_constructor => _child, $child_name, $name);
570 continue;
571 }
572 )*
573 return Err(crate::util::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
574 }
575 Ok($elem {
576 $(
577 $attr: get_attr!(elem, $attr_name, $attr_action),
578 )*
579 $(
580 $child_ident: finish_parse_elem!($child_ident: $coucou = $child_name, $name),
581 )*
582 $(
583 $text_ident: $codec::decode(&elem.text())?,
584 )*
585 })
586 }
587 }
588
589 impl From<$elem> for ::minidom::Element {
590 fn from(elem: $elem) -> ::minidom::Element {
591 ::minidom::Element::builder($name)
592 .ns(crate::ns::$ns)
593 $(
594 .attr($attr_name, elem.$attr)
595 )*
596 $(
597 .append(generate_serialiser!(elem, $child_ident, $coucou, $child_constructor, ($child_name, $child_ns)))
598 )*
599 $(
600 .append($codec::encode(&elem.$text_ident))
601 )*
602 .build()
603 }
604 }
605 );
606}
607
608#[cfg(test)]
609macro_rules! assert_size (
610 ($t:ty, $sz:expr) => (
611 assert_eq!(::std::mem::size_of::<$t>(), $sz);
612 );
613);
614
615// TODO: move that to src/pubsub/mod.rs, once we figure out how to use macros from there.
616macro_rules! impl_pubsub_item {
617 ($item:ident, $ns:ident) => {
618 impl crate::TryFrom<crate::Element> for $item {
619 type Err = Error;
620
621 fn try_from(elem: crate::Element) -> Result<$item, Error> {
622 check_self!(elem, "item", $ns);
623 check_no_unknown_attributes!(elem, "item", ["id", "publisher"]);
624 let mut payloads = elem.children().cloned().collect::<Vec<_>>();
625 let payload = payloads.pop();
626 if !payloads.is_empty() {
627 return Err(Error::ParseError(
628 "More than a single payload in item element.",
629 ));
630 }
631 Ok($item(crate::pubsub::Item {
632 id: get_attr!(elem, "id", Option),
633 publisher: get_attr!(elem, "publisher", Option),
634 payload,
635 }))
636 }
637 }
638
639 impl From<$item> for crate::Element {
640 fn from(item: $item) -> crate::Element {
641 crate::Element::builder("item")
642 .ns(ns::$ns)
643 .attr("id", item.0.id)
644 .attr("publisher", item.0.publisher)
645 .append(item.0.payload)
646 .build()
647 }
648 }
649
650 impl ::std::ops::Deref for $item {
651 type Target = crate::pubsub::Item;
652
653 fn deref(&self) -> &Self::Target {
654 &self.0
655 }
656 }
657
658 impl ::std::ops::DerefMut for $item {
659 fn deref_mut(&mut self) -> &mut Self::Target {
660 &mut self.0
661 }
662 }
663 }
664}