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 {
|
|
|
|
($elem:ident, $attr:tt, $type:tt) => (
|
|
|
|
get_attr!($elem, $attr, $type, value, value.parse()?)
|
|
|
|
);
|
2017-11-24 05:09:25 +00:00
|
|
|
($elem:ident, $attr:tt, optional_empty, $value:ident, $func:expr) => (
|
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some("") => None,
|
|
|
|
Some($value) => Some($func),
|
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
);
|
2017-10-31 21:17:24 +00:00
|
|
|
($elem:ident, $attr:tt, optional, $value:ident, $func:expr) => (
|
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some($value) => Some($func),
|
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
($elem:ident, $attr:tt, required, $value:ident, $func:expr) => (
|
|
|
|
match $elem.attr($attr) {
|
|
|
|
Some($value) => $func,
|
2018-05-14 14:21:39 +00:00
|
|
|
None => return Err(::error::Error::ParseError(concat!("Required attribute '", $attr, "' missing."))),
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
($elem:ident, $attr:tt, default, $value:ident, $func:expr) => (
|
|
|
|
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
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_attribute {
|
2018-05-14 22:18:15 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+,}) => (
|
|
|
|
generate_attribute!($(#[$meta])* $elem, $name, {$($(#[$a_meta])* $a => $b),+});
|
2017-10-31 21:17:24 +00:00
|
|
|
);
|
2018-05-14 22:18:15 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+,}, Default = $default:ident) => (
|
|
|
|
generate_attribute!($(#[$meta])* $elem, $name, {$($(#[$a_meta])* $a => $b),+}, Default = $default);
|
2017-10-31 21:17:24 +00:00
|
|
|
);
|
2018-05-14 22:18:15 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+}) => (
|
|
|
|
$(#[$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 {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, ::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
Ok(match s {
|
|
|
|
$($b => $elem::$a),+,
|
2018-05-14 14:21:39 +00:00
|
|
|
_ => return Err(::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
|
2017-10-31 21:17:24 +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),+
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2018-05-14 22:18:15 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+}, Default = $default:ident) => (
|
|
|
|
$(#[$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 {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, ::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
Ok(match s {
|
|
|
|
$($b => $elem::$a),+,
|
2018-05-14 14:21:39 +00:00
|
|
|
_ => return Err(::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
|
2017-10-31 21:17:24 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
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 {
|
|
|
|
type Err = ::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self, ::error::Error> {
|
|
|
|
Ok(match s {
|
|
|
|
"true" | "1" => $elem::True,
|
|
|
|
"false" | "0" => $elem::False,
|
|
|
|
_ => return Err(::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
2017-11-24 04:27:35 +00:00
|
|
|
macro_rules! generate_element_enum {
|
2018-05-14 14:30:28 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+,}) => (
|
2017-11-24 04:27:35 +00:00
|
|
|
generate_element_enum!($(#[$meta])* $elem, $name, $ns, {$($(#[$enum_meta])* $enum => $enum_name),+});
|
|
|
|
);
|
2018-05-14 14:30:28 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+}) => (
|
2017-11-24 04:27:35 +00:00
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum $elem {
|
|
|
|
$(
|
|
|
|
$(#[$enum_meta])*
|
|
|
|
$enum
|
|
|
|
),+
|
|
|
|
}
|
2018-05-14 14:17:21 +00:00
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
2017-11-24 04:27:35 +00:00
|
|
|
check_ns_only!(elem, $name, $ns);
|
|
|
|
check_no_children!(elem, $name);
|
|
|
|
check_no_attributes!(elem, $name);
|
|
|
|
Ok(match elem.name() {
|
|
|
|
$($enum_name => $elem::$enum,)+
|
2018-05-14 14:21:39 +00:00
|
|
|
_ => return Err(::error::Error::ParseError(concat!("This is not a ", $name, " element."))),
|
2017-11-24 04:27:35 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:17:21 +00:00
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder(match elem {
|
2017-11-24 04:27:35 +00:00
|
|
|
$($elem::$enum => $enum_name,)+
|
2018-05-14 14:30:28 +00:00
|
|
|
}).ns(::ns::$ns)
|
2017-11-24 04:27:35 +00:00
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-11-24 05:44:58 +00:00
|
|
|
macro_rules! generate_attribute_enum {
|
2018-05-14 14:30:28 +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
|
|
|
generate_attribute_enum!($(#[$meta])* $elem, $name, $ns, $attr, {$($(#[$enum_meta])* $enum => $enum_name),+});
|
|
|
|
);
|
2018-05-14 14:30:28 +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 {
|
|
|
|
$(
|
|
|
|
$(#[$enum_meta])*
|
|
|
|
$enum
|
|
|
|
),+
|
|
|
|
}
|
2018-05-14 14:17:21 +00:00
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
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]);
|
|
|
|
Ok(match get_attr!(elem, $attr, required) {
|
|
|
|
$($enum_name => $elem::$enum,)+
|
2018-05-14 14:21:39 +00:00
|
|
|
_ => return Err(::error::Error::ParseError(concat!("Invalid ", $name, " ", $attr, " value."))),
|
2017-11-24 05:44:58 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:17:21 +00:00
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
2018-05-14 14:30:28 +00:00
|
|
|
.ns(::ns::$ns)
|
2017-11-24 05:44:58 +00:00
|
|
|
.attr($attr, match elem {
|
|
|
|
$($elem::$enum => $enum_name,)+
|
|
|
|
})
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-10-31 21:17:24 +00:00
|
|
|
macro_rules! check_self {
|
2018-05-14 14:30:28 +00:00
|
|
|
($elem:ident, $name:tt, $ns:ident) => (
|
2017-10-31 21:17:24 +00:00
|
|
|
check_self!($elem, $name, $ns, $name);
|
|
|
|
);
|
2018-05-14 14:30:28 +00:00
|
|
|
($elem:ident, $name:tt, $ns:ident, $pretty_name:tt) => (
|
|
|
|
if !$elem.is($name, ::ns::$ns) {
|
2018-05-14 14:21:39 +00:00
|
|
|
return Err(::error::Error::ParseError(concat!("This is not a ", $pretty_name, " element.")));
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_ns_only {
|
2018-05-14 14:30:28 +00:00
|
|
|
($elem:ident, $name:tt, $ns:ident) => (
|
|
|
|
if !$elem.has_ns(::ns::$ns) {
|
2018-05-14 14:21:39 +00:00
|
|
|
return Err(::error::Error::ParseError(concat!("This is not a ", $name, " element.")));
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_no_children {
|
|
|
|
($elem:ident, $name:tt) => (
|
|
|
|
for _ in $elem.children() {
|
2018-05-14 14:21:39 +00:00
|
|
|
return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_no_attributes {
|
|
|
|
($elem:ident, $name:tt) => (
|
2018-05-12 18:25:59 +00:00
|
|
|
for _ in $elem.attrs() {
|
2018-05-14 14:21:39 +00:00
|
|
|
return Err(::error::Error::ParseError(concat!("Unknown attribute in ", $name, " element.")));
|
2018-05-12 18:25:59 +00:00
|
|
|
}
|
2017-10-31 21:17:24 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! check_no_unknown_attributes {
|
|
|
|
($elem:ident, $name:tt, [$($attr:tt),*]) => (
|
|
|
|
for (_attr, _) in $elem.attrs() {
|
|
|
|
$(
|
|
|
|
if _attr == $attr {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
)*
|
2018-05-14 14:21:39 +00:00
|
|
|
return Err(::error::Error::ParseError(concat!("Unknown attribute in ", $name, " element.")));
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_empty_element {
|
2018-05-14 14:30:28 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident) => (
|
2017-10-31 21:17:24 +00:00
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct $elem;
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
2017-10-31 21:17:24 +00:00
|
|
|
|
2018-05-14 14:21:39 +00:00
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_children!(elem, $name);
|
|
|
|
check_no_attributes!(elem, $name);
|
|
|
|
Ok($elem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(_: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
2018-05-14 14:30:28 +00:00
|
|
|
.ns(::ns::$ns)
|
2017-10-31 21:17:24 +00:00
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_element_with_only_attributes {
|
2018-05-14 14:30:28 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),+,]) => (
|
2017-10-31 21:17:24 +00:00
|
|
|
generate_element_with_only_attributes!($(#[$meta])* $elem, $name, $ns, [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*]);
|
|
|
|
);
|
2018-05-14 14:30:28 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),+]) => (
|
2017-10-31 21:17:24 +00:00
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct $elem {
|
|
|
|
$(
|
|
|
|
$(#[$attr_meta])*
|
2017-11-23 16:06:35 +00:00
|
|
|
pub $attr: $attr_type,
|
|
|
|
)*
|
2017-10-31 21:17:24 +00:00
|
|
|
}
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
2017-10-31 21:17:24 +00:00
|
|
|
|
2018-05-14 14:21:39 +00:00
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
2017-10-31 21:17:24 +00:00
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_children!(elem, $name);
|
|
|
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
|
|
|
Ok($elem {
|
|
|
|
$(
|
2017-11-23 16:06:35 +00:00
|
|
|
$attr: get_attr!(elem, $attr_name, $attr_action),
|
|
|
|
)*
|
2017-10-31 21:17:24 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
2018-05-14 14:30:28 +00:00
|
|
|
.ns(::ns::$ns)
|
2017-10-31 21:17:24 +00:00
|
|
|
$(
|
|
|
|
.attr($attr_name, elem.$attr)
|
|
|
|
)*
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! generate_id {
|
|
|
|
($elem:ident) => (
|
|
|
|
#[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 {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, ::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)))
|
|
|
|
}
|
|
|
|
}
|
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 {
|
2018-05-14 15:32:15 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns: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 {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
|
|
|
fn from_str(s: &str) -> Result<$elem, ::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)))
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:17:21 +00:00
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
2017-11-24 05:09:25 +00:00
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_children!(elem, $name);
|
|
|
|
check_no_attributes!(elem, $name);
|
|
|
|
// TODO: add a way to parse that differently when needed.
|
|
|
|
Ok($elem(elem.text()))
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 14:17:21 +00:00
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
2018-05-14 14:30:28 +00:00
|
|
|
.ns(::ns::$ns)
|
2017-10-31 21:17:24 +00:00
|
|
|
.append(elem.0)
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2017-11-16 20:17:11 +00:00
|
|
|
|
|
|
|
macro_rules! generate_element_with_text {
|
2018-05-14 14:30:28 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $text_ident:ident: $codec:ident < $text_type:ty >) => (
|
2018-02-20 16:01:12 +00:00
|
|
|
generate_element_with_text!($(#[$meta])* $elem, $name, $ns, [], $text_ident: $codec<$text_type>);
|
|
|
|
);
|
2018-05-14 14:30:28 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], $text_ident:ident: $codec:ident < $text_type:ty >) => (
|
2017-11-16 20:17:11 +00:00
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct $elem {
|
|
|
|
$(
|
|
|
|
$(#[$attr_meta])*
|
2017-11-23 16:06:35 +00:00
|
|
|
pub $attr: $attr_type,
|
|
|
|
)*
|
2017-11-16 20:17:11 +00:00
|
|
|
pub $text_ident: $text_type,
|
|
|
|
}
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
2017-11-16 20:17:11 +00:00
|
|
|
|
2018-05-14 14:21:39 +00:00
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
2017-11-16 20:17:11 +00:00
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_children!(elem, $name);
|
|
|
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
|
|
|
Ok($elem {
|
|
|
|
$(
|
2017-11-23 16:06:35 +00:00
|
|
|
$attr: get_attr!(elem, $attr_name, $attr_action),
|
|
|
|
)*
|
2017-11-16 20:17:11 +00:00
|
|
|
$text_ident: $codec::decode(&elem.text())?,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
2018-05-14 14:30:28 +00:00
|
|
|
.ns(::ns::$ns)
|
2017-11-16 20:17:11 +00:00
|
|
|
$(
|
|
|
|
.attr($attr_name, elem.$attr)
|
|
|
|
)*
|
|
|
|
.append($codec::encode(&elem.$text_ident))
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2017-11-16 21:00:01 +00:00
|
|
|
|
|
|
|
macro_rules! generate_element_with_children {
|
2018-05-14 23:55:16 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
|
|
|
|
generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], children: [$($(#[$child_meta])* $child_ident: Vec<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
|
|
|
|
);
|
2018-05-14 19:04:16 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
|
|
|
|
generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], children: [$($(#[$child_meta])* $child_ident: Vec<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
|
|
|
|
);
|
2018-05-14 15:32:15 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
|
2017-11-16 21:00:01 +00:00
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct $elem {
|
|
|
|
$(
|
|
|
|
$(#[$attr_meta])*
|
2017-11-23 16:06:35 +00:00
|
|
|
pub $attr: $attr_type,
|
|
|
|
)*
|
2017-11-16 21:00:01 +00:00
|
|
|
$(
|
|
|
|
$(#[$child_meta])*
|
2017-11-23 16:06:35 +00:00
|
|
|
pub $child_ident: Vec<$child_type>,
|
|
|
|
)*
|
2017-11-16 21:00:01 +00:00
|
|
|
}
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
2018-05-14 14:21:39 +00:00
|
|
|
type Err = ::error::Error;
|
2017-11-16 21:00:01 +00:00
|
|
|
|
2018-05-14 14:21:39 +00:00
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
2017-11-16 21:00:01 +00:00
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
|
|
|
let mut parsed_children = vec!();
|
|
|
|
for child in elem.children() {
|
|
|
|
$(
|
2018-05-14 14:30:28 +00:00
|
|
|
if child.is($child_name, ::ns::$child_ns) {
|
2017-11-23 16:32:18 +00:00
|
|
|
let parsed_child = $child_constructor::try_from(child.clone())?;
|
|
|
|
parsed_children.push(parsed_child);
|
|
|
|
continue;
|
|
|
|
}
|
2017-11-16 21:00:01 +00:00
|
|
|
)*
|
2018-05-14 14:21:39 +00:00
|
|
|
return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
|
2017-11-16 21:00:01 +00:00
|
|
|
}
|
|
|
|
Ok($elem {
|
|
|
|
$(
|
2017-11-23 16:06:35 +00:00
|
|
|
$attr: get_attr!(elem, $attr_name, $attr_action),
|
|
|
|
)*
|
2017-11-16 21:00:01 +00:00
|
|
|
$(
|
2017-11-23 16:06:35 +00:00
|
|
|
$child_ident: parsed_children,
|
2017-11-16 21:00:01 +00:00
|
|
|
)*
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-14 14:17:21 +00:00
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
2018-05-14 14:30:28 +00:00
|
|
|
.ns(::ns::$ns)
|
2017-11-16 21:00:01 +00:00
|
|
|
$(
|
|
|
|
.attr($attr_name, elem.$attr)
|
|
|
|
)*
|
2017-11-23 16:30:53 +00:00
|
|
|
$(
|
|
|
|
.append(elem.$child_ident)
|
|
|
|
)*
|
2017-11-16 21:00:01 +00:00
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2018-05-14 19:04:16 +00:00
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
|
|
|
|
generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], child: ($(#[$child_meta])* $child_ident: Option<$child_type> = ($child_name, $child_ns) => $child_constructor));
|
|
|
|
);
|
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
|
|
|
|
generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], child: ($(#[$child_meta])* $child_ident: Option<$child_type> = ($child_name, $child_ns) => $child_constructor));
|
|
|
|
);
|
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
|
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct $elem {
|
|
|
|
$(
|
|
|
|
$(#[$attr_meta])*
|
|
|
|
pub $attr: $attr_type,
|
|
|
|
)*
|
|
|
|
$(#[$child_meta])*
|
|
|
|
pub $child_ident: Option<$child_type>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
|
|
|
type Err = ::error::Error;
|
|
|
|
|
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
|
|
|
let mut parsed_child = None;
|
|
|
|
for child in elem.children() {
|
|
|
|
if child.is($child_name, ::ns::$child_ns) {
|
|
|
|
parsed_child = Some($child_constructor::try_from(child.clone())?);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
|
|
|
|
}
|
|
|
|
Ok($elem {
|
|
|
|
$(
|
|
|
|
$attr: get_attr!(elem, $attr_name, $attr_action),
|
|
|
|
)*
|
|
|
|
$child_ident: parsed_child,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
|
|
|
.ns(::ns::$ns)
|
|
|
|
$(
|
|
|
|
.attr($attr_name, elem.$attr)
|
|
|
|
)*
|
|
|
|
.append(elem.$child_ident)
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
|
|
|
|
generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], child: ($(#[$child_meta])* $child_ident: $child_type = ($child_name, $child_ns) => $child_constructor));
|
|
|
|
);
|
|
|
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
|
|
|
|
$(#[$meta])*
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct $elem {
|
|
|
|
$(
|
|
|
|
$(#[$attr_meta])*
|
|
|
|
pub $attr: $attr_type,
|
|
|
|
)*
|
|
|
|
$(#[$child_meta])*
|
|
|
|
pub $child_ident: $child_type,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::try_from::TryFrom<::minidom::Element> for $elem {
|
|
|
|
type Err = ::error::Error;
|
|
|
|
|
|
|
|
fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
|
|
|
|
check_self!(elem, $name, $ns);
|
|
|
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
|
|
|
let mut parsed_child = None;
|
|
|
|
for child in elem.children() {
|
|
|
|
if child.is($child_name, ::ns::$child_ns) {
|
|
|
|
parsed_child = Some($child_constructor::try_from(child.clone())?);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
|
|
|
|
}
|
|
|
|
Ok($elem {
|
|
|
|
$(
|
|
|
|
$attr: get_attr!(elem, $attr_name, $attr_action),
|
|
|
|
)*
|
|
|
|
$child_ident: parsed_child.ok_or(::error::Error::ParseError(concat!("Missing child ", $child_name, " in ", $name, " element.")))?,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<$elem> for ::minidom::Element {
|
|
|
|
fn from(elem: $elem) -> ::minidom::Element {
|
|
|
|
::minidom::Element::builder($name)
|
|
|
|
.ns(::ns::$ns)
|
|
|
|
$(
|
|
|
|
.attr($attr_name, elem.$attr)
|
|
|
|
)*
|
|
|
|
.append(elem.$child_ident)
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2017-11-16 21:00:01 +00:00
|
|
|
}
|