// Copyright (c) 2017 Emmanuel Gil Peyrot // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. use try_from::TryFrom; use minidom::Element; use error::Error; use ns; #[derive(Debug, Clone)] pub struct Set { pub after: Option, pub before: Option, pub count: Option, pub first: Option, pub first_index: Option, pub index: Option, pub last: Option, pub max: Option, } impl TryFrom for Set { type Err = Error; fn try_from(elem: Element) -> Result { if !elem.is("set", ns::RSM) { return Err(Error::ParseError("This is not a RSM element.")); } let mut set = Set { after: None, before: None, count: None, first: None, first_index: None, index: None, last: None, max: None, }; for child in elem.children() { if child.is("after", ns::RSM) { if set.after.is_some() { return Err(Error::ParseError("Set can’t have more than one after.")); } set.after = Some(child.text()); } else if child.is("before", ns::RSM) { if set.before.is_some() { return Err(Error::ParseError("Set can’t have more than one before.")); } set.before = Some(child.text()); } else if child.is("count", ns::RSM) { if set.count.is_some() { return Err(Error::ParseError("Set can’t have more than one count.")); } set.count = Some(child.text().parse()?); } else if child.is("first", ns::RSM) { if set.first.is_some() { return Err(Error::ParseError("Set can’t have more than one first.")); } set.first_index = get_attr!(child, "index", optional); set.first = Some(child.text()); } else if child.is("index", ns::RSM) { if set.index.is_some() { return Err(Error::ParseError("Set can’t have more than one index.")); } set.index = Some(child.text().parse()?); } else if child.is("last", ns::RSM) { if set.last.is_some() { return Err(Error::ParseError("Set can’t have more than one last.")); } set.last = Some(child.text()); } else if child.is("max", ns::RSM) { if set.max.is_some() { return Err(Error::ParseError("Set can’t have more than one max.")); } set.max = Some(child.text().parse()?); } else { return Err(Error::ParseError("Unknown child in set element.")); } } Ok(set) } } impl From for Element { fn from(set: Set) -> Element { let first = set.first.clone() .map(|first| Element::builder("first") .ns(ns::RSM) .attr("index", set.first_index) .append(first) .build()); Element::builder("set") .ns(ns::RSM) .append(set.after.map(|after| Element::builder("after").ns(ns::RSM).append(after).build())) .append(set.before.map(|before| Element::builder("before").ns(ns::RSM).append(before).build())) .append(set.count.map(|count| Element::builder("count").ns(ns::RSM).append(format!("{}", count)).build())) .append(first) .append(set.index.map(|index| Element::builder("index").ns(ns::RSM).append(format!("{}", index)).build())) .append(set.last.map(|last| Element::builder("last").ns(ns::RSM).append(last).build())) .append(set.max.map(|max| Element::builder("max").ns(ns::RSM).append(format!("{}", max)).build())) .build() } } #[cfg(test)] mod tests { use super::*; use compare_elements::NamespaceAwareCompare; #[test] fn test_simple() { let elem: Element = "".parse().unwrap(); let set = Set::try_from(elem).unwrap(); assert_eq!(set.after, None); assert_eq!(set.before, None); assert_eq!(set.count, None); match set.first { Some(_) => panic!(), None => (), } assert_eq!(set.index, None); assert_eq!(set.last, None); assert_eq!(set.max, None); } #[test] fn test_unknown() { let elem: Element = "".parse().unwrap(); let error = Set::try_from(elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), }; assert_eq!(message, "This is not a RSM element."); } #[test] fn test_invalid_child() { let elem: Element = "".parse().unwrap(); let error = Set::try_from(elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), }; assert_eq!(message, "Unknown child in set element."); } #[test] fn test_serialise() { let elem: Element = "".parse().unwrap(); let rsm = Set { after: None, before: None, count: None, first: None, first_index: None, index: None, last: None, max: None, }; let elem2 = rsm.into(); assert_eq!(elem, elem2); } #[test] fn test_first_index() { let elem: Element = "coucou".parse().unwrap(); let elem1 = elem.clone(); let set = Set::try_from(elem).unwrap(); assert_eq!(set.first, Some(String::from("coucou"))); assert_eq!(set.first_index, Some(4)); let set2 = Set { after: None, before: None, count: None, first: Some(String::from("coucou")), first_index: Some(4), index: None, last: None, max: None, }; let elem2 = set2.into(); assert!(elem1.compare_to(&elem2)); } }