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