1// Copyright (c) 2017 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
7use std::convert::TryFrom;
8
9use minidom::Element;
10
11use error::Error;
12
13use ns;
14
15#[derive(Debug, Clone)]
16pub struct First {
17 pub index: Option<usize>,
18 pub base: String,
19}
20
21#[derive(Debug, Clone)]
22pub struct Set {
23 pub after: Option<String>,
24 pub before: Option<String>,
25 pub count: Option<usize>,
26 pub first: Option<First>,
27 pub index: Option<usize>,
28 pub last: Option<String>,
29 pub max: Option<usize>,
30}
31
32impl<'a> TryFrom<&'a Element> for Set {
33 type Error = Error;
34
35 fn try_from(elem: &'a Element) -> Result<Set, Error> {
36 if !elem.is("set", ns::RSM) {
37 return Err(Error::ParseError("This is not a RSM element."));
38 }
39 let mut after = None;
40 let mut before = None;
41 let mut count = None;
42 let mut first = None;
43 let mut index = None;
44 let mut last = None;
45 let mut max = None;
46 for child in elem.children() {
47 if child.is("after", ns::RSM) {
48 if after.is_some() {
49 return Err(Error::ParseError("Set can’t have more than one after."));
50 }
51 after = Some(child.text());
52 } else if child.is("before", ns::RSM) {
53 if before.is_some() {
54 return Err(Error::ParseError("Set can’t have more than one before."));
55 }
56 before = Some(child.text());
57 } else if child.is("count", ns::RSM) {
58 if count.is_some() {
59 return Err(Error::ParseError("Set can’t have more than one count."));
60 }
61 count = Some(child.text().parse()?);
62 } else if child.is("first", ns::RSM) {
63 if first.is_some() {
64 return Err(Error::ParseError("Set can’t have more than one first."));
65 }
66 first = Some(First {
67 index: match child.attr("index") {
68 Some(index) => Some(index.parse()?),
69 None => None,
70 },
71 base: child.text(),
72 });
73 } else if child.is("index", ns::RSM) {
74 if index.is_some() {
75 return Err(Error::ParseError("Set can’t have more than one index."));
76 }
77 index = Some(child.text().parse()?);
78 } else if child.is("last", ns::RSM) {
79 if last.is_some() {
80 return Err(Error::ParseError("Set can’t have more than one last."));
81 }
82 last = Some(child.text());
83 } else if child.is("max", ns::RSM) {
84 if max.is_some() {
85 return Err(Error::ParseError("Set can’t have more than one max."));
86 }
87 max = Some(child.text().parse()?);
88 } else {
89 return Err(Error::ParseError("Unknown child in set element."));
90 }
91 }
92 Ok(Set {
93 after: after,
94 before: before,
95 count: count,
96 first: first,
97 index: index,
98 last: last,
99 max: max,
100 })
101 }
102}
103
104impl<'a> Into<Element> for &'a Set {
105 fn into(self) -> Element {
106 let mut elem = Element::builder("set")
107 .ns(ns::RSM)
108 .build();
109 if self.after.is_some() {
110 elem.append_child(Element::builder("after").ns(ns::RSM).append(self.after.clone()).build());
111 }
112 if self.before.is_some() {
113 elem.append_child(Element::builder("before").ns(ns::RSM).append(self.before.clone()).build());
114 }
115 if self.count.is_some() {
116 elem.append_child(Element::builder("count").ns(ns::RSM).append(format!("{}", self.count.unwrap())).build());
117 }
118 if self.first.is_some() {
119 let first = self.first.clone().unwrap();
120 elem.append_child(Element::builder("first")
121 .ns(ns::RSM)
122 .attr("index", match first.index {
123 Some(index) => Some(format!("{}", index)),
124 None => None,
125 })
126 .append(first.base.clone()).build());
127 }
128 if self.index.is_some() {
129 elem.append_child(Element::builder("index").ns(ns::RSM).append(format!("{}", self.index.unwrap())).build());
130 }
131 if self.last.is_some() {
132 elem.append_child(Element::builder("last").ns(ns::RSM).append(self.last.clone()).build());
133 }
134 if self.max.is_some() {
135 elem.append_child(Element::builder("max").ns(ns::RSM).append(format!("{}", self.max.unwrap())).build());
136 }
137 elem
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn test_simple() {
147 let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>".parse().unwrap();
148 let set = Set::try_from(&elem).unwrap();
149 assert_eq!(set.after, None);
150 assert_eq!(set.before, None);
151 assert_eq!(set.count, None);
152 match set.first {
153 Some(_) => panic!(),
154 None => (),
155 }
156 assert_eq!(set.index, None);
157 assert_eq!(set.last, None);
158 assert_eq!(set.max, None);
159 }
160
161 #[test]
162 fn test_unknown() {
163 let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0'/>".parse().unwrap();
164 let error = Set::try_from(&elem).unwrap_err();
165 let message = match error {
166 Error::ParseError(string) => string,
167 _ => panic!(),
168 };
169 assert_eq!(message, "This is not a RSM element.");
170 }
171
172 #[test]
173 fn test_invalid_child() {
174 let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'><coucou/></set>".parse().unwrap();
175 let error = Set::try_from(&elem).unwrap_err();
176 let message = match error {
177 Error::ParseError(string) => string,
178 _ => panic!(),
179 };
180 assert_eq!(message, "Unknown child in set element.");
181 }
182
183 #[test]
184 fn test_serialise() {
185 let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>".parse().unwrap();
186 let rsm = Set {
187 after: None,
188 before: None,
189 count: None,
190 first: None,
191 index: None,
192 last: None,
193 max: None,
194 };
195 let elem2 = (&rsm).into();
196 assert_eq!(elem, elem2);
197 }
198}