aboutsummaryrefslogtreecommitdiffstats
path: root/stanza/src/xep_0030/info.rs
blob: 94cbabbc2f30af62963e2424c7d3bdd6afda0fe6 (plain) (blame)
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
use peanuts::{
    element::{FromElement, IntoElement},
    DeserializeError, Element,
};

#[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_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()?;

        Ok(Self {
            node,
            features,
            identities,
            #[cfg(feature = "xep_0059")]
            set,
        })
    }
}

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());

        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,
}

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()));
        }

        Ok(Self {
            category,
            name,
            r#type,
        })
    }
}

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())
    }
}