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