rsm.rs

  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}