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