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