2018-03-01 09:01:35 +00:00
|
|
|
// Copyright (c) 2017-2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
2017-10-31 21:17:24 +00:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
macro_rules! get_attr {
|
2018-12-18 14:32:05 +00:00
|
|
|
($elem:ident, $attr:tt, $type:tt) => {
|
2024-06-21 14:27:43 +00:00
|
|
|
get_attr!(
|
|
|
|
$elem,
|
|
|
|
$attr,
|
|
|
|
$type,
|
|
|
|
value,
|
|
|
|
value.parse().map_err(xso::error::Error::text_parse_error)?
|
|
|
|
)
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-02-24 19:26:40 +00:00
|
|
|
($elem:ident, $attr:tt, OptionEmpty, $value:ident, $func:expr) => {
|
2017-11-24 05:09:25 +00:00
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some("") => None,
|
|
|
|
Some($value) => Some($func),
|
|
|
|
None => None,
|
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-02-24 19:26:40 +00:00
|
|
|
($elem:ident, $attr:tt, Option, $value:ident, $func:expr) => {
|
2017-10-31 21:17:24 +00:00
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some($value) => Some($func),
|
|
|
|
None => None,
|
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-02-24 19:26:40 +00:00
|
|
|
($elem:ident, $attr:tt, Required, $value:ident, $func:expr) => {
|
2017-10-31 21:17:24 +00:00
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some($value) => $func,
|
2018-12-18 14:32:05 +00:00
|
|
|
None => {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(
|
|
|
|
concat!("Required attribute '", $attr, "' missing.").into(),
|
|
|
|
)
|
|
|
|
.into());
|
2018-12-18 14:32:05 +00:00
|
|
|
}
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-02-28 01:26:10 +00:00
|
|
|
($elem:ident, $attr:tt, RequiredNonEmpty, $value:ident, $func:expr) => {
|
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some("") => {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(
|
|
|
|
concat!("Required attribute '", $attr, "' must not be empty.").into(),
|
|
|
|
)
|
|
|
|
.into());
|
2019-10-22 23:32:41 +00:00
|
|
|
}
|
2019-02-28 01:26:10 +00:00
|
|
|
Some($value) => $func,
|
|
|
|
None => {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(
|
|
|
|
concat!("Required attribute '", $attr, "' missing.").into(),
|
|
|
|
)
|
|
|
|
.into());
|
2019-02-28 01:26:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2019-02-24 19:26:40 +00:00
|
|
|
($elem:ident, $attr:tt, Default, $value:ident, $func:expr) => {
|
2017-10-31 21:17:24 +00:00
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some($value) => $func,
|
2018-05-14 19:03:24 +00:00
|
|
|
None => ::std::default::Default::default(),
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_attribute {
|
2022-03-22 14:58:54 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+$(,)?}) => (
|
2018-05-14 22:18:15 +00:00
|
|
|
$(#[$meta])*
|
2017-10-31 21:17:24 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum $elem {
|
|
|
|
$(
|
2018-05-14 22:18:15 +00:00
|
|
|
$(#[$a_meta])*
|
2017-10-31 21:17:24 +00:00
|
|
|
$a
|
|
|
|
),+
|
|
|
|
}
|
2018-05-14 14:11:22 +00:00
|
|
|
impl ::std::str::FromStr for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Err = xso::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
Ok(match s {
|
|
|
|
$($b => $elem::$a),+,
|
2024-06-21 14:27:43 +00:00
|
|
|
_ => return Err(xso::error::Error::Other(concat!("Unknown value for '", $name, "' attribute.")).into()),
|
2017-10-31 21:17:24 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-06-26 11:12:33 +00:00
|
|
|
impl ::xso::FromXmlText for $elem {
|
|
|
|
fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
|
|
|
|
s.parse().map_err(xso::error::Error::text_parse_error)
|
|
|
|
}
|
|
|
|
}
|
2019-10-18 11:05:33 +00:00
|
|
|
impl std::fmt::Display for $elem {
|
|
|
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
|
|
|
write!(fmt, "{}", match self {
|
|
|
|
$($elem::$a => $b),+
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-07-09 15:01:42 +00:00
|
|
|
impl ::xso::AsXmlText for $elem {
|
|
|
|
fn as_xml_text(&self) -> Result<::std::borrow::Cow<'_, str>, xso::error::Error> {
|
|
|
|
match self {
|
|
|
|
$(
|
|
|
|
$elem::$a => Ok(::std::borrow::Cow::Borrowed($b))
|
|
|
|
),+
|
|
|
|
}
|
2024-06-26 11:12:33 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:12:56 +00:00
|
|
|
impl ::minidom::IntoAttributeValue for $elem {
|
2017-10-31 21:17:24 +00:00
|
|
|
fn into_attribute_value(self) -> Option<String> {
|
|
|
|
Some(String::from(match self {
|
|
|
|
$($elem::$a => $b),+
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2022-03-22 14:58:54 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+$(,)?}, Default = $default:ident) => (
|
2018-05-14 22:18:15 +00:00
|
|
|
$(#[$meta])*
|
2017-10-31 21:17:24 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum $elem {
|
|
|
|
$(
|
2018-05-14 22:18:15 +00:00
|
|
|
$(#[$a_meta])*
|
2017-10-31 21:17:24 +00:00
|
|
|
$a
|
|
|
|
),+
|
|
|
|
}
|
2018-05-14 14:11:22 +00:00
|
|
|
impl ::std::str::FromStr for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Err = xso::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
Ok(match s {
|
|
|
|
$($b => $elem::$a),+,
|
2024-06-21 14:27:43 +00:00
|
|
|
_ => return Err(xso::error::Error::Other(concat!("Unknown value for '", $name, "' attribute.")).into()),
|
2017-10-31 21:17:24 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-06-29 14:34:27 +00:00
|
|
|
impl ::xso::FromXmlText for $elem {
|
|
|
|
fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
|
|
|
|
s.parse().map_err(xso::error::Error::text_parse_error)
|
|
|
|
}
|
|
|
|
}
|
2024-07-09 15:01:42 +00:00
|
|
|
impl ::xso::AsXmlText for $elem {
|
|
|
|
fn as_xml_text(&self) -> Result<std::borrow::Cow<'_, str>, xso::error::Error> {
|
|
|
|
Ok(std::borrow::Cow::Borrowed(match self {
|
2024-06-29 14:34:27 +00:00
|
|
|
$($elem::$a => $b),+
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unreachable_patterns)]
|
2024-07-09 15:01:42 +00:00
|
|
|
fn as_optional_xml_text(&self) -> Result<Option<std::borrow::Cow<'_, str>>, xso::error::Error> {
|
|
|
|
Ok(Some(std::borrow::Cow::Borrowed(match self {
|
2024-06-29 14:34:27 +00:00
|
|
|
$elem::$default => return Ok(None),
|
|
|
|
$($elem::$a => $b),+
|
|
|
|
})))
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:12:56 +00:00
|
|
|
impl ::minidom::IntoAttributeValue for $elem {
|
2017-10-31 21:17:24 +00:00
|
|
|
#[allow(unreachable_patterns)]
|
|
|
|
fn into_attribute_value(self) -> Option<String> {
|
|
|
|
Some(String::from(match self {
|
|
|
|
$elem::$default => return None,
|
|
|
|
$($elem::$a => $b),+
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 19:03:24 +00:00
|
|
|
impl ::std::default::Default for $elem {
|
2017-10-31 21:17:24 +00:00
|
|
|
fn default() -> $elem {
|
|
|
|
$elem::$default
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2019-01-12 21:50:22 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, ($(#[$meta_symbol:meta])* $symbol:ident => $value:tt)) => (
|
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum $elem {
|
|
|
|
$(#[$meta_symbol])*
|
|
|
|
$symbol,
|
|
|
|
/// Value when absent.
|
|
|
|
None,
|
|
|
|
}
|
|
|
|
impl ::std::str::FromStr for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Err = xso::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self, xso::error::Error> {
|
2019-01-12 21:50:22 +00:00
|
|
|
Ok(match s {
|
|
|
|
$value => $elem::$symbol,
|
2024-06-21 14:27:43 +00:00
|
|
|
_ => return Err(xso::error::Error::Other(concat!("Unknown value for '", $name, "' attribute."))),
|
2019-01-12 21:50:22 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl ::minidom::IntoAttributeValue for $elem {
|
|
|
|
fn into_attribute_value(self) -> Option<String> {
|
|
|
|
match self {
|
|
|
|
$elem::$symbol => Some(String::from($value)),
|
|
|
|
$elem::None => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl ::std::default::Default for $elem {
|
|
|
|
fn default() -> $elem {
|
|
|
|
$elem::None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2018-05-14 22:18:15 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, bool) => (
|
|
|
|
$(#[$meta])*
|
2018-05-14 19:04:16 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum $elem {
|
|
|
|
/// True value, represented by either 'true' or '1'.
|
|
|
|
True,
|
|
|
|
/// False value, represented by either 'false' or '0'.
|
|
|
|
False,
|
|
|
|
}
|
|
|
|
impl ::std::str::FromStr for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Err = xso::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self, xso::error::Error> {
|
2018-05-14 19:04:16 +00:00
|
|
|
Ok(match s {
|
|
|
|
"true" | "1" => $elem::True,
|
|
|
|
"false" | "0" => $elem::False,
|
2024-06-21 14:27:43 +00:00
|
|
|
_ => return Err(xso::error::Error::Other(concat!("Unknown value for '", $name, "' attribute."))),
|
2018-05-14 19:04:16 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-06-26 17:35:56 +00:00
|
|
|
impl ::xso::FromXmlText for $elem {
|
|
|
|
fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
|
|
|
|
match s.parse::<bool>().map_err(xso::error::Error::text_parse_error)? {
|
|
|
|
true => Ok(Self::True),
|
|
|
|
false => Ok(Self::False),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-07-09 15:01:42 +00:00
|
|
|
impl ::xso::AsXmlText for $elem {
|
|
|
|
fn as_xml_text(&self) -> Result<::std::borrow::Cow<'_, str>, xso::error::Error> {
|
2024-06-26 17:35:56 +00:00
|
|
|
match self {
|
2024-07-09 15:01:42 +00:00
|
|
|
Self::True => Ok(::std::borrow::Cow::Borrowed("true")),
|
|
|
|
Self::False => Ok(::std::borrow::Cow::Borrowed("false")),
|
2024-06-26 17:35:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-09 15:01:42 +00:00
|
|
|
fn as_optional_xml_text(&self) -> Result<Option<::std::borrow::Cow<'_, str>>, xso::error::Error> {
|
2024-06-26 17:35:56 +00:00
|
|
|
match self {
|
2024-07-09 15:01:42 +00:00
|
|
|
Self::True => Ok(Some(::std::borrow::Cow::Borrowed("true"))),
|
2024-06-26 17:35:56 +00:00
|
|
|
Self::False => Ok(None),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 19:04:16 +00:00
|
|
|
impl ::minidom::IntoAttributeValue for $elem {
|
|
|
|
fn into_attribute_value(self) -> Option<String> {
|
|
|
|
match self {
|
|
|
|
$elem::True => Some(String::from("true")),
|
|
|
|
$elem::False => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl ::std::default::Default for $elem {
|
|
|
|
fn default() -> $elem {
|
|
|
|
$elem::False
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2019-02-28 02:10:21 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $type:tt, Default = $default:expr) => (
|
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub struct $elem(pub $type);
|
|
|
|
impl ::std::str::FromStr for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Err = xso::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self, xso::error::Error> {
|
|
|
|
Ok($elem($type::from_str(s).map_err(xso::error::Error::text_parse_error)?))
|
2019-02-28 02:10:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
impl ::minidom::IntoAttributeValue for $elem {
|
|
|
|
fn into_attribute_value(self) -> Option<String> {
|
|
|
|
match self {
|
|
|
|
$elem($default) => None,
|
|
|
|
$elem(value) => Some(format!("{}", value)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl ::std::default::Default for $elem {
|
|
|
|
fn default() -> $elem {
|
|
|
|
$elem($default)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
2017-11-24 05:44:58 +00:00
|
|
|
macro_rules! generate_attribute_enum {
|
2022-03-22 14:58:54 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $attr:tt, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+$(,)?}) => (
|
2017-11-24 05:44:58 +00:00
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum $elem {
|
|
|
|
$(
|
2018-12-29 17:29:11 +00:00
|
|
|
$(#[$enum_meta])*
|
|
|
|
$enum
|
2017-11-24 05:44:58 +00:00
|
|
|
),+
|
|
|
|
}
|
2024-07-24 18:28:22 +00:00
|
|
|
impl ::std::convert::TryFrom<minidom::Element> for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Error = xso::error::FromElementError;
|
2024-07-24 18:28:22 +00:00
|
|
|
fn try_from(elem: minidom::Element) -> Result<$elem, xso::error::FromElementError> {
|
2017-11-24 05:44:58 +00:00
|
|
|
check_ns_only!(elem, $name, $ns);
|
|
|
|
check_no_children!(elem, $name);
|
|
|
|
check_no_unknown_attributes!(elem, $name, [$attr]);
|
2019-02-24 19:48:19 +00:00
|
|
|
Ok(match get_attr!(elem, $attr, Required) {
|
2017-11-24 05:44:58 +00:00
|
|
|
$($enum_name => $elem::$enum,)+
|
2024-06-21 14:27:43 +00:00
|
|
|
_ => return Err(xso::error::Error::Other(concat!("Invalid ", $name, " ", $attr, " value.")).into()),
|
2017-11-24 05:44:58 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-07-24 18:28:22 +00:00
|
|
|
impl From<$elem> for minidom::Element {
|
|
|
|
fn from(elem: $elem) -> minidom::Element {
|
|
|
|
minidom::Element::builder($name, crate::ns::$ns)
|
2018-12-29 17:29:11 +00:00
|
|
|
.attr($attr, match elem {
|
|
|
|
$($elem::$enum => $enum_name,)+
|
|
|
|
})
|
|
|
|
.build()
|
2017-11-24 05:44:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-10-31 21:17:24 +00:00
|
|
|
macro_rules! check_self {
|
2018-12-18 14:32:05 +00:00
|
|
|
($elem:ident, $name:tt, $ns:ident) => {
|
2017-10-31 21:17:24 +00:00
|
|
|
check_self!($elem, $name, $ns, $name);
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2024-03-02 08:19:49 +00:00
|
|
|
($elem:ident, $name:tt, $ns:ident, $pretty_name:tt) => {
|
|
|
|
if !$elem.is($name, crate::ns::$ns) {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::FromElementError::Mismatch($elem));
|
2024-03-02 08:19:49 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_child {
|
|
|
|
($elem:ident, $name:tt, $ns:ident) => {
|
|
|
|
check_child!($elem, $name, $ns, $name);
|
|
|
|
};
|
2018-12-18 14:32:05 +00:00
|
|
|
($elem:ident, $name:tt, $ns:ident, $pretty_name:tt) => {
|
2018-12-18 14:27:30 +00:00
|
|
|
if !$elem.is($name, crate::ns::$ns) {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(
|
|
|
|
concat!("This is not a ", $pretty_name, " element.").into(),
|
|
|
|
)
|
|
|
|
.into());
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_ns_only {
|
2018-12-18 14:32:05 +00:00
|
|
|
($elem:ident, $name:tt, $ns:ident) => {
|
2018-12-18 14:27:30 +00:00
|
|
|
if !$elem.has_ns(crate::ns::$ns) {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(
|
|
|
|
concat!("This is not a ", $name, " element.").into(),
|
|
|
|
)
|
|
|
|
.into());
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_no_children {
|
2018-12-18 14:32:05 +00:00
|
|
|
($elem:ident, $name:tt) => {
|
2019-01-12 21:00:46 +00:00
|
|
|
#[cfg(not(feature = "disable-validation"))]
|
2017-10-31 21:17:24 +00:00
|
|
|
for _ in $elem.children() {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(
|
|
|
|
concat!("Unknown child in ", $name, " element.").into(),
|
|
|
|
)
|
|
|
|
.into());
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_no_attributes {
|
2018-12-18 14:32:05 +00:00
|
|
|
($elem:ident, $name:tt) => {
|
2019-01-12 21:00:46 +00:00
|
|
|
#[cfg(not(feature = "disable-validation"))]
|
2018-05-12 18:25:59 +00:00
|
|
|
for _ in $elem.attrs() {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(
|
|
|
|
concat!("Unknown attribute in ", $name, " element.").into(),
|
|
|
|
)
|
|
|
|
.into());
|
2018-05-12 18:25:59 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_no_unknown_attributes {
|
|
|
|
($elem:ident, $name:tt, [$($attr:tt),*]) => (
|
2019-01-12 21:00:46 +00:00
|
|
|
#[cfg(not(feature = "disable-validation"))]
|
2017-10-31 21:17:24 +00:00
|
|
|
for (_attr, _) in $elem.attrs() {
|
|
|
|
$(
|
2018-12-29 17:29:11 +00:00
|
|
|
if _attr == $attr {
|
|
|
|
continue;
|
|
|
|
}
|
2017-10-31 21:17:24 +00:00
|
|
|
)*
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(concat!("Unknown attribute in ", $name, " element.")).into());
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_id {
|
2018-07-02 11:47:32 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident) => (
|
|
|
|
$(#[$meta])*
|
2017-10-31 21:17:24 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub struct $elem(pub String);
|
2018-05-14 14:11:22 +00:00
|
|
|
impl ::std::str::FromStr for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Err = xso::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
// TODO: add a way to parse that differently when needed.
|
|
|
|
Ok($elem(String::from(s)))
|
|
|
|
}
|
|
|
|
}
|
2024-06-26 11:12:33 +00:00
|
|
|
impl ::xso::FromXmlText for $elem {
|
|
|
|
fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
|
|
|
|
Ok(Self(s))
|
|
|
|
}
|
|
|
|
}
|
2024-07-09 15:01:42 +00:00
|
|
|
impl ::xso::AsXmlText for $elem {
|
|
|
|
fn as_xml_text(&self) ->Result<::std::borrow::Cow<'_, str>, xso::error::Error> {
|
|
|
|
Ok(::std::borrow::Cow::Borrowed(self.0.as_str()))
|
2024-06-26 11:12:33 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:12:56 +00:00
|
|
|
impl ::minidom::IntoAttributeValue for $elem {
|
2017-10-31 21:17:24 +00:00
|
|
|
fn into_attribute_value(self) -> Option<String> {
|
|
|
|
Some(self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_elem_id {
|
2024-06-29 14:14:12 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:literal, $ns:ident) => (
|
2019-09-05 13:34:21 +00:00
|
|
|
generate_elem_id!($(#[$meta])* $elem, $name, $ns, String);
|
2018-05-14 14:11:22 +00:00
|
|
|
impl ::std::str::FromStr for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Err = xso::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, xso::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
// TODO: add a way to parse that differently when needed.
|
|
|
|
Ok($elem(String::from(s)))
|
|
|
|
}
|
|
|
|
}
|
2019-09-05 13:34:21 +00:00
|
|
|
);
|
2024-06-29 14:14:12 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:literal, $ns:ident, $type:ty) => (
|
2019-09-05 13:34:21 +00:00
|
|
|
$(#[$meta])*
|
2024-06-29 14:14:12 +00:00
|
|
|
#[derive(xso::FromXml, xso::AsXml, Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
#[xml(namespace = crate::ns::$ns, name = $name)]
|
|
|
|
pub struct $elem(#[xml(text)] pub $type);
|
2017-10-31 21:17:24 +00:00
|
|
|
);
|
|
|
|
}
|
2017-11-16 20:17:11 +00:00
|
|
|
|
2019-02-24 19:26:40 +00:00
|
|
|
macro_rules! decl_attr {
|
|
|
|
(OptionEmpty, $type:ty) => (
|
|
|
|
Option<$type>
|
|
|
|
);
|
|
|
|
(Option, $type:ty) => (
|
|
|
|
Option<$type>
|
|
|
|
);
|
|
|
|
(Required, $type:ty) => (
|
|
|
|
$type
|
|
|
|
);
|
2019-02-28 01:26:10 +00:00
|
|
|
(RequiredNonEmpty, $type:ty) => (
|
|
|
|
$type
|
|
|
|
);
|
2019-02-24 19:26:40 +00:00
|
|
|
(Default, $type:ty) => (
|
|
|
|
$type
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-05-28 14:29:51 +00:00
|
|
|
macro_rules! start_decl {
|
|
|
|
(Vec, $type:ty) => (
|
|
|
|
Vec<$type>
|
2018-05-14 23:55:16 +00:00
|
|
|
);
|
2018-05-28 14:29:51 +00:00
|
|
|
(Option, $type:ty) => (
|
|
|
|
Option<$type>
|
2018-05-14 19:04:16 +00:00
|
|
|
);
|
2018-05-28 14:29:51 +00:00
|
|
|
(Required, $type:ty) => (
|
|
|
|
$type
|
|
|
|
);
|
2019-09-08 13:53:55 +00:00
|
|
|
(Present, $type:ty) => (
|
|
|
|
bool
|
|
|
|
);
|
2018-05-28 14:29:51 +00:00
|
|
|
}
|
2017-11-16 21:00:01 +00:00
|
|
|
|
2018-05-28 14:29:51 +00:00
|
|
|
macro_rules! start_parse_elem {
|
2018-12-18 14:32:05 +00:00
|
|
|
($temp:ident: Vec) => {
|
2018-05-28 14:29:51 +00:00
|
|
|
let mut $temp = Vec::new();
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($temp:ident: Option) => {
|
2018-05-28 14:29:51 +00:00
|
|
|
let mut $temp = None;
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($temp:ident: Required) => {
|
2018-05-28 14:29:51 +00:00
|
|
|
let mut $temp = None;
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-09-08 13:53:55 +00:00
|
|
|
($temp:ident: Present) => {
|
|
|
|
let mut $temp = false;
|
|
|
|
};
|
2018-05-28 14:29:51 +00:00
|
|
|
}
|
2018-05-14 19:04:16 +00:00
|
|
|
|
2018-05-28 14:29:51 +00:00
|
|
|
macro_rules! do_parse {
|
2018-12-18 14:32:05 +00:00
|
|
|
($elem:ident, Element) => {
|
2024-03-02 09:07:34 +00:00
|
|
|
Ok($elem)
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($elem:ident, String) => {
|
2024-03-02 09:07:34 +00:00
|
|
|
Ok($elem.text())
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($elem:ident, $constructor:ident) => {
|
2024-06-21 14:27:43 +00:00
|
|
|
$constructor::try_from($elem).map_err(xso::error::Error::from)
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2018-05-28 14:29:51 +00:00
|
|
|
}
|
2018-05-14 19:04:16 +00:00
|
|
|
|
2018-05-28 14:29:51 +00:00
|
|
|
macro_rules! do_parse_elem {
|
2018-12-18 14:32:05 +00:00
|
|
|
($temp:ident: Vec = $constructor:ident => $elem:ident, $name:tt, $parent_name:tt) => {
|
2024-03-02 09:07:34 +00:00
|
|
|
match do_parse!($elem, $constructor) {
|
|
|
|
Ok(v) => Ok($temp.push(v)),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($temp:ident: Option = $constructor:ident => $elem:ident, $name:tt, $parent_name:tt) => {
|
2018-05-28 14:29:51 +00:00
|
|
|
if $temp.is_some() {
|
2024-06-21 14:27:43 +00:00
|
|
|
Err(xso::error::Error::Other(
|
|
|
|
concat!(
|
|
|
|
"Element ",
|
|
|
|
$parent_name,
|
|
|
|
" must not have more than one ",
|
|
|
|
$name,
|
|
|
|
" child."
|
|
|
|
)
|
|
|
|
.into(),
|
|
|
|
))
|
2024-03-02 09:07:34 +00:00
|
|
|
} else {
|
|
|
|
match do_parse!($elem, $constructor) {
|
|
|
|
Ok(v) => {
|
|
|
|
$temp = Some(v);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}
|
2018-05-14 19:04:16 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($temp:ident: Required = $constructor:ident => $elem:ident, $name:tt, $parent_name:tt) => {
|
2018-05-28 15:04:40 +00:00
|
|
|
if $temp.is_some() {
|
2024-06-21 14:27:43 +00:00
|
|
|
Err(xso::error::Error::Other(
|
|
|
|
concat!(
|
|
|
|
"Element ",
|
|
|
|
$parent_name,
|
|
|
|
" must not have more than one ",
|
|
|
|
$name,
|
|
|
|
" child."
|
|
|
|
)
|
|
|
|
.into(),
|
|
|
|
))
|
2024-03-02 09:07:34 +00:00
|
|
|
} else {
|
|
|
|
match do_parse!($elem, $constructor) {
|
|
|
|
Ok(v) => {
|
|
|
|
$temp = Some(v);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}
|
2018-05-28 15:04:40 +00:00
|
|
|
}
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-09-08 13:53:55 +00:00
|
|
|
($temp:ident: Present = $constructor:ident => $elem:ident, $name:tt, $parent_name:tt) => {
|
|
|
|
if $temp {
|
2024-06-21 14:27:43 +00:00
|
|
|
Err(xso::error::Error::Other(
|
|
|
|
concat!(
|
|
|
|
"Element ",
|
|
|
|
$parent_name,
|
|
|
|
" must not have more than one ",
|
|
|
|
$name,
|
|
|
|
" child."
|
|
|
|
)
|
|
|
|
.into(),
|
|
|
|
))
|
2024-03-02 09:07:34 +00:00
|
|
|
} else {
|
|
|
|
$temp = true;
|
|
|
|
Ok(())
|
2019-09-08 13:53:55 +00:00
|
|
|
}
|
|
|
|
};
|
2018-05-28 14:29:51 +00:00
|
|
|
}
|
2018-05-14 19:04:16 +00:00
|
|
|
|
2018-05-28 14:29:51 +00:00
|
|
|
macro_rules! finish_parse_elem {
|
2018-12-18 14:32:05 +00:00
|
|
|
($temp:ident: Vec = $name:tt, $parent_name:tt) => {
|
2018-05-28 14:29:51 +00:00
|
|
|
$temp
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($temp:ident: Option = $name:tt, $parent_name:tt) => {
|
2018-05-28 14:29:51 +00:00
|
|
|
$temp
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
|
|
|
($temp:ident: Required = $name:tt, $parent_name:tt) => {
|
2024-06-21 14:27:43 +00:00
|
|
|
$temp.ok_or(xso::error::Error::Other(
|
|
|
|
concat!("Missing child ", $name, " in ", $parent_name, " element.").into(),
|
|
|
|
))?
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-09-08 13:53:55 +00:00
|
|
|
($temp:ident: Present = $name:tt, $parent_name:tt) => {
|
|
|
|
$temp
|
|
|
|
};
|
2018-05-28 14:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_serialiser {
|
2019-07-24 22:20:38 +00:00
|
|
|
($builder:ident, $parent:ident, $elem:ident, Required, String, ($name:tt, $ns:ident)) => {
|
2019-09-06 14:03:58 +00:00
|
|
|
$builder.append(
|
2024-07-24 18:28:22 +00:00
|
|
|
minidom::Element::builder($name, crate::ns::$ns)
|
2019-10-22 23:32:41 +00:00
|
|
|
.append(::minidom::Node::Text($parent.$elem)),
|
2019-07-24 22:20:38 +00:00
|
|
|
)
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2019-07-24 22:20:38 +00:00
|
|
|
($builder:ident, $parent:ident, $elem:ident, Option, String, ($name:tt, $ns:ident)) => {
|
|
|
|
$builder.append_all($parent.$elem.map(|elem| {
|
2024-07-24 18:28:22 +00:00
|
|
|
minidom::Element::builder($name, crate::ns::$ns).append(::minidom::Node::Text(elem))
|
2019-10-22 23:32:41 +00:00
|
|
|
}))
|
2019-07-24 22:20:38 +00:00
|
|
|
};
|
2019-10-12 15:10:36 +00:00
|
|
|
($builder:ident, $parent:ident, $elem:ident, Option, $constructor:ident, ($name:tt, *)) => {
|
2019-11-27 17:17:10 +00:00
|
|
|
$builder.append_all(
|
|
|
|
$parent
|
|
|
|
.$elem
|
2024-07-24 18:28:22 +00:00
|
|
|
.map(|elem| ::minidom::Node::Element(minidom::Element::from(elem))),
|
2019-11-27 17:17:10 +00:00
|
|
|
)
|
2019-10-12 15:10:36 +00:00
|
|
|
};
|
2019-07-24 22:20:38 +00:00
|
|
|
($builder:ident, $parent:ident, $elem:ident, Option, $constructor:ident, ($name:tt, $ns:ident)) => {
|
2019-11-27 17:17:10 +00:00
|
|
|
$builder.append_all(
|
|
|
|
$parent
|
|
|
|
.$elem
|
2024-07-24 18:28:22 +00:00
|
|
|
.map(|elem| ::minidom::Node::Element(minidom::Element::from(elem))),
|
2019-11-27 17:17:10 +00:00
|
|
|
)
|
2019-07-24 22:20:38 +00:00
|
|
|
};
|
|
|
|
($builder:ident, $parent:ident, $elem:ident, Vec, $constructor:ident, ($name:tt, $ns:ident)) => {
|
|
|
|
$builder.append_all($parent.$elem.into_iter())
|
|
|
|
};
|
2019-09-08 13:53:55 +00:00
|
|
|
($builder:ident, $parent:ident, $elem:ident, Present, $constructor:ident, ($name:tt, $ns:ident)) => {
|
2023-09-05 15:08:30 +00:00
|
|
|
$builder.append_all(
|
|
|
|
$parent
|
|
|
|
.$elem
|
2024-07-24 18:28:22 +00:00
|
|
|
.then(|| minidom::Element::builder($name, crate::ns::$ns)),
|
2023-09-05 15:08:30 +00:00
|
|
|
)
|
2019-09-08 13:53:55 +00:00
|
|
|
};
|
2019-07-24 22:20:38 +00:00
|
|
|
($builder:ident, $parent:ident, $elem:ident, $_:ident, $constructor:ident, ($name:tt, $ns:ident)) => {
|
2024-07-24 18:28:22 +00:00
|
|
|
$builder.append(::minidom::Node::Element(minidom::Element::from(
|
2019-10-22 23:32:41 +00:00
|
|
|
$parent.$elem,
|
|
|
|
)))
|
2018-12-18 14:32:05 +00:00
|
|
|
};
|
2018-05-28 14:29:51 +00:00
|
|
|
}
|
|
|
|
|
2019-10-12 15:10:36 +00:00
|
|
|
macro_rules! generate_child_test {
|
|
|
|
($child:ident, $name:tt, *) => {
|
2019-11-09 00:31:36 +00:00
|
|
|
$child.is($name, ::minidom::NSChoice::Any)
|
2019-10-12 15:10:36 +00:00
|
|
|
};
|
|
|
|
($child:ident, $name:tt, $ns:tt) => {
|
|
|
|
$child.is($name, crate::ns::$ns)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-05-28 14:42:35 +00:00
|
|
|
macro_rules! generate_element {
|
2022-03-22 14:58:54 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_action:tt<$attr_type:ty> = $attr_name:tt),+$(,)?]) => (
|
2019-02-24 19:26:40 +00:00
|
|
|
generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_action<$attr_type> = $attr_name),*], children: []);
|
2018-05-28 14:42:35 +00:00
|
|
|
);
|
2022-03-22 14:58:54 +00:00
|
|
|
($(#[$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:tt) => $child_constructor:ident),+$(,)?]) => (
|
2018-05-28 14:45:13 +00:00
|
|
|
generate_element!($(#[$meta])* $elem, $name, $ns, attributes: [], children: [$($(#[$child_meta])* $child_ident: $coucou<$child_type> = ($child_name, $child_ns) => $child_constructor),*]);
|
2018-05-28 14:29:51 +00:00
|
|
|
);
|
2024-07-24 15:50:35 +00:00
|
|
|
($(#[$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:tt) => $child_constructor:ident),*$(,)?]) => (
|
2018-05-14 19:04:16 +00:00
|
|
|
$(#[$meta])*
|
2020-11-29 20:17:51 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
2018-05-14 19:04:16 +00:00
|
|
|
pub struct $elem {
|
|
|
|
$(
|
2018-12-29 17:29:11 +00:00
|
|
|
$(#[$attr_meta])*
|
2019-02-24 19:26:40 +00:00
|
|
|
pub $attr: decl_attr!($attr_action, $attr_type),
|
2018-05-14 19:04:16 +00:00
|
|
|
)*
|
2018-05-28 14:29:51 +00:00
|
|
|
$(
|
2018-12-29 17:29:11 +00:00
|
|
|
$(#[$child_meta])*
|
|
|
|
pub $child_ident: start_decl!($coucou, $child_type),
|
2018-05-28 14:29:51 +00:00
|
|
|
)*
|
2018-05-14 19:04:16 +00:00
|
|
|
}
|
|
|
|
|
2024-06-16 08:14:18 +00:00
|
|
|
impl ::xso::FromXml for $elem {
|
|
|
|
type Builder = ::xso::minidom_compat::FromEventsViaElement<$elem>;
|
|
|
|
|
|
|
|
fn from_events(
|
|
|
|
qname: ::xso::exports::rxml::QName,
|
|
|
|
attrs: ::xso::exports::rxml::AttrMap,
|
|
|
|
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
|
|
|
|
if qname.0 != crate::ns::$ns || qname.1 != $name {
|
|
|
|
return Err(::xso::error::FromEventsError::Mismatch {
|
|
|
|
name: qname,
|
|
|
|
attrs,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
Self::Builder::new(qname, attrs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-24 18:28:22 +00:00
|
|
|
impl ::std::convert::TryFrom<minidom::Element> for $elem {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Error = xso::error::FromElementError;
|
2018-05-14 19:04:16 +00:00
|
|
|
|
2024-07-24 18:28:22 +00:00
|
|
|
fn try_from(mut elem: minidom::Element) -> Result<$elem, xso::error::FromElementError> {
|
2018-05-14 19:04:16 +00:00
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
2018-05-28 14:29:51 +00:00
|
|
|
$(
|
2018-12-29 17:29:11 +00:00
|
|
|
start_parse_elem!($child_ident: $coucou);
|
2018-05-28 14:29:51 +00:00
|
|
|
)*
|
2024-03-02 09:07:34 +00:00
|
|
|
for _child in elem.take_contents_as_children() {
|
|
|
|
let residual = _child;
|
|
|
|
$(
|
|
|
|
// TODO: get rid of the explicit generate_child_test here
|
|
|
|
// once !295 has landed.
|
|
|
|
let residual = if generate_child_test!(residual, $child_name, $child_ns) {
|
|
|
|
match do_parse_elem!($child_ident: $coucou = $child_constructor => residual, $child_name, $name) {
|
|
|
|
Ok(()) => continue,
|
2024-06-21 14:27:43 +00:00
|
|
|
Err(other) => return Err(other.into()),
|
2024-03-02 09:07:34 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
residual
|
|
|
|
};
|
|
|
|
)*
|
|
|
|
let _ = residual;
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(xso::error::Error::Other(concat!("Unknown child in ", $name, " element.")).into());
|
2018-05-14 19:04:16 +00:00
|
|
|
}
|
|
|
|
Ok($elem {
|
|
|
|
$(
|
2018-12-29 17:29:11 +00:00
|
|
|
$attr: get_attr!(elem, $attr_name, $attr_action),
|
2018-05-14 19:04:16 +00:00
|
|
|
)*
|
2018-05-28 14:29:51 +00:00
|
|
|
$(
|
2018-12-29 17:29:11 +00:00
|
|
|
$child_ident: finish_parse_elem!($child_ident: $coucou = $child_name, $name),
|
2018-05-28 14:29:51 +00:00
|
|
|
)*
|
2018-05-14 19:04:16 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-24 18:28:22 +00:00
|
|
|
impl From<$elem> for minidom::Element {
|
|
|
|
fn from(elem: $elem) -> minidom::Element {
|
|
|
|
let mut builder = minidom::Element::builder($name, crate::ns::$ns);
|
2019-07-24 22:20:38 +00:00
|
|
|
$(
|
|
|
|
builder = builder.attr($attr_name, elem.$attr);
|
|
|
|
)*
|
|
|
|
$(
|
|
|
|
builder = generate_serialiser!(builder, elem, $child_ident, $coucou, $child_constructor, ($child_name, $child_ns));
|
|
|
|
)*
|
|
|
|
|
|
|
|
builder.build()
|
|
|
|
}
|
|
|
|
}
|
2024-06-16 08:14:18 +00:00
|
|
|
|
2024-07-09 15:01:42 +00:00
|
|
|
impl ::xso::AsXml for $elem {
|
|
|
|
type ItemIter<'x> = ::xso::minidom_compat::AsItemsViaElement<'x>;
|
2024-06-16 08:14:18 +00:00
|
|
|
|
2024-07-09 15:01:42 +00:00
|
|
|
fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, ::xso::error::Error> {
|
|
|
|
::xso::minidom_compat::AsItemsViaElement::new(self.clone())
|
2024-06-16 08:14:18 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-14 19:04:16 +00:00
|
|
|
);
|
2017-11-16 21:00:01 +00:00
|
|
|
}
|
2018-10-26 12:26:16 +00:00
|
|
|
|
2018-12-18 14:43:49 +00:00
|
|
|
#[cfg(test)]
|
2018-10-26 12:26:16 +00:00
|
|
|
macro_rules! assert_size (
|
|
|
|
($t:ty, $sz:expr) => (
|
|
|
|
assert_eq!(::std::mem::size_of::<$t>(), $sz);
|
|
|
|
);
|
|
|
|
);
|
2019-01-27 17:57:25 +00:00
|
|
|
|
|
|
|
// TODO: move that to src/pubsub/mod.rs, once we figure out how to use macros from there.
|
|
|
|
macro_rules! impl_pubsub_item {
|
|
|
|
($item:ident, $ns:ident) => {
|
2024-07-24 18:28:22 +00:00
|
|
|
impl ::std::convert::TryFrom<minidom::Element> for $item {
|
2024-06-21 14:27:43 +00:00
|
|
|
type Error = FromElementError;
|
2019-01-27 17:57:25 +00:00
|
|
|
|
2024-07-24 18:28:22 +00:00
|
|
|
fn try_from(mut elem: minidom::Element) -> Result<$item, FromElementError> {
|
2019-01-27 17:57:25 +00:00
|
|
|
check_self!(elem, "item", $ns);
|
|
|
|
check_no_unknown_attributes!(elem, "item", ["id", "publisher"]);
|
2024-03-02 09:07:34 +00:00
|
|
|
let mut payloads = elem.take_contents_as_children().collect::<Vec<_>>();
|
2019-01-27 17:57:25 +00:00
|
|
|
let payload = payloads.pop();
|
|
|
|
if !payloads.is_empty() {
|
2024-06-21 14:27:43 +00:00
|
|
|
return Err(Error::Other("More than a single payload in item element.").into());
|
2019-01-27 17:57:25 +00:00
|
|
|
}
|
|
|
|
Ok($item(crate::pubsub::Item {
|
2019-02-24 19:48:19 +00:00
|
|
|
id: get_attr!(elem, "id", Option),
|
|
|
|
publisher: get_attr!(elem, "publisher", Option),
|
2019-01-27 17:57:25 +00:00
|
|
|
payload,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-24 18:28:22 +00:00
|
|
|
impl From<$item> for minidom::Element {
|
|
|
|
fn from(item: $item) -> minidom::Element {
|
|
|
|
minidom::Element::builder("item", ns::$ns)
|
2019-01-27 17:57:25 +00:00
|
|
|
.attr("id", item.0.id)
|
|
|
|
.attr("publisher", item.0.publisher)
|
2019-09-06 14:03:58 +00:00
|
|
|
.append_all(item.0.payload)
|
2019-01-27 17:57:25 +00:00
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::Deref for $item {
|
|
|
|
type Target = crate::pubsub::Item;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::DerefMut for $item {
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
&mut self.0
|
|
|
|
}
|
|
|
|
}
|
2019-10-22 23:32:41 +00:00
|
|
|
};
|
2019-01-27 17:57:25 +00:00
|
|
|
}
|