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 mut elem = Element::builder("set")
 92                               .ns(ns::RSM)
 93                               .build();
 94        if set.after.is_some() {
 95            elem.append_child(Element::builder("after").ns(ns::RSM).append(set.after).build());
 96        }
 97        if set.before.is_some() {
 98            elem.append_child(Element::builder("before").ns(ns::RSM).append(set.before).build());
 99        }
100        if let Some(count) = set.count {
101            elem.append_child(Element::builder("count").ns(ns::RSM).append(format!("{}", count)).build());
102        }
103        if set.first.is_some() {
104            elem.append_child(Element::builder("first")
105                                      .ns(ns::RSM)
106                                      .attr("index", set.first_index)
107                                      .append(set.first).build());
108        }
109        if let Some(index) = set.index {
110            elem.append_child(Element::builder("index").ns(ns::RSM).append(format!("{}", index)).build());
111        }
112        if set.last.is_some() {
113            elem.append_child(Element::builder("last").ns(ns::RSM).append(set.last).build());
114        }
115        if let Some(max) = set.max {
116            elem.append_child(Element::builder("max").ns(ns::RSM).append(format!("{}", max)).build());
117        }
118        elem
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125    use compare_elements::NamespaceAwareCompare;
126
127    #[test]
128    fn test_simple() {
129        let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>".parse().unwrap();
130        let set = Set::try_from(elem).unwrap();
131        assert_eq!(set.after, None);
132        assert_eq!(set.before, None);
133        assert_eq!(set.count, None);
134        match set.first {
135            Some(_) => panic!(),
136            None => (),
137        }
138        assert_eq!(set.index, None);
139        assert_eq!(set.last, None);
140        assert_eq!(set.max, None);
141    }
142
143    #[test]
144    fn test_unknown() {
145        let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0'/>".parse().unwrap();
146        let error = Set::try_from(elem).unwrap_err();
147        let message = match error {
148            Error::ParseError(string) => string,
149            _ => panic!(),
150        };
151        assert_eq!(message, "This is not a RSM element.");
152    }
153
154    #[test]
155    fn test_invalid_child() {
156        let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'><coucou/></set>".parse().unwrap();
157        let error = Set::try_from(elem).unwrap_err();
158        let message = match error {
159            Error::ParseError(string) => string,
160            _ => panic!(),
161        };
162        assert_eq!(message, "Unknown child in set element.");
163    }
164
165    #[test]
166    fn test_serialise() {
167        let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>".parse().unwrap();
168        let rsm = Set {
169            after: None,
170            before: None,
171            count: None,
172            first: None,
173            first_index: None,
174            index: None,
175            last: None,
176            max: None,
177        };
178        let elem2 = rsm.into();
179        assert_eq!(elem, elem2);
180    }
181
182    #[test]
183    fn test_first_index() {
184        let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'><first index='4'>coucou</first></set>".parse().unwrap();
185        let elem1 = elem.clone();
186        let set = Set::try_from(elem).unwrap();
187        assert_eq!(set.first, Some(String::from("coucou")));
188        assert_eq!(set.first_index, Some(4));
189
190        let set2 = Set {
191            after: None,
192            before: None,
193            count: None,
194            first: Some(String::from("coucou")),
195            first_index: Some(4),
196            index: None,
197            last: None,
198            max: None,
199        };
200        let elem2 = set2.into();
201        assert!(elem1.compare_to(&elem2));
202    }
203}