1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
use peanuts::{
element::{FromElement, IntoElement},
DeserializeError, Element, XML_NS,
};
#[cfg(feature = "xep_0128")]
use crate::xep_0004::X;
#[cfg(feature = "xep_0059")]
use crate::xep_0059::Set;
pub const XMLNS: &str = "http://jabber.org/protocol/disco#info";
#[derive(Debug, Clone)]
pub struct Query {
pub node: Option<String>,
pub features: Vec<Feature>,
pub identities: Vec<Identity>,
#[cfg(feature = "xep_0128")]
pub extensions: Vec<X>,
#[cfg(feature = "xep_0059")]
pub set: Option<Set>,
}
impl FromElement for Query {
fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("query")?;
element.check_namespace(XMLNS)?;
let node = element.attribute_opt("node")?;
let features = element.children()?;
let identities = element.children()?;
#[cfg(feature = "xep_0059")]
let set = element.child_opt()?;
#[cfg(feature = "xep_0128")]
let extensions = element.children()?;
Ok(Self {
node,
features,
identities,
#[cfg(feature = "xep_0059")]
set,
#[cfg(feature = "xep_0128")]
extensions,
})
}
}
impl IntoElement for Query {
fn builder(&self) -> peanuts::element::ElementBuilder {
let builder = Element::builder("query", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_children(self.features.clone())
.push_children(self.identities.clone());
#[cfg(feature = "xep_0059")]
let builder = builder.push_child_opt(self.set.clone());
#[cfg(feature = "xep_0128")]
let builder = builder.push_children(self.extensions.clone());
builder
}
}
// no children
#[derive(Debug, Clone)]
pub struct Identity {
/// non empty string
pub category: String,
pub name: Option<String>,
/// non empty string
pub r#type: String,
pub lang: Option<String>,
}
impl FromElement for Identity {
fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("identity")?;
element.check_namespace(XMLNS)?;
let category: String = element.attribute("category")?;
if category.is_empty() {
return Err(DeserializeError::AttributeEmptyString(
"category".to_string(),
));
}
let name = element.attribute_opt("name")?;
let r#type: String = element.attribute("type")?;
if r#type.is_empty() {
return Err(DeserializeError::AttributeEmptyString("type".to_string()));
}
let lang = element.attribute_opt_namespaced("lang", XML_NS)?;
Ok(Self {
category,
name,
r#type,
lang,
})
}
}
impl IntoElement for Identity {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("identity", Some(XMLNS))
.push_attribute("category", self.category.clone())
.push_attribute_opt("name", self.name.clone())
.push_attribute("type", self.r#type.clone())
}
}
// no children
#[derive(Debug, Clone)]
pub struct Feature {
pub var: String,
}
impl FromElement for Feature {
fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
element.check_name("feature")?;
element.check_namespace(XMLNS)?;
let var = element.attribute("var")?;
Ok(Self { var })
}
}
impl IntoElement for Feature {
fn builder(&self) -> peanuts::element::ElementBuilder {
Element::builder("feature", Some(XMLNS)).push_attribute("var", self.var.clone())
}
}
|