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