// 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 xso::{AsXml, FromXml}; use crate::ns; /// Requests paging through a potentially big set of items (represented by an /// UID). #[derive(FromXml, AsXml, Debug, Clone, PartialEq)] #[xml(namespace = ns::RSM, name = "set")] pub struct SetQuery { /// Limit the number of items, or use the recipient’s defaults if None. #[xml(extract(default, fields(text(type_ = usize))))] pub max: Option, /// The UID after which to give results, or if None it is the element /// “before” the first item, effectively an index of negative one. #[xml(extract(default, fields(text(type_ = String))))] pub after: Option, /// The UID before which to give results, or if None it starts with the /// last page of the full set. #[xml(extract(default, fields(text(type_ = String))))] pub before: Option, /// Numerical index of the page (deprecated). #[xml(extract(default, fields(text(type_ = usize))))] pub index: Option, } /// The first item of the page. #[derive(FromXml, AsXml, Debug, Clone, PartialEq)] #[xml(namespace = ns::RSM, name = "first")] pub struct First { /// The position of the [first item](#structfield.item) in the full set /// (which may be approximate). #[xml(attribute(default))] pub index: Option, /// The UID of the first item of the page. #[xml(text)] pub item: String, } /// Describes the paging result of a [query](struct.SetQuery.html). #[derive(FromXml, AsXml, Debug, Clone, PartialEq)] #[xml(namespace = ns::RSM, name = "set")] pub struct SetResult { /// The first item of the page. #[xml(child(default))] pub first: Option, /// The UID of the last item of the page. #[xml(extract(default, fields(text(type_ = String))))] pub last: Option, /// How many items there are in the full set (which may be approximate). #[xml(extract(default, fields(text(type_ = usize))))] pub count: Option, } #[cfg(test)] mod tests { use super::*; use minidom::Element; use xso::error::{Error, FromElementError}; #[cfg(target_pointer_width = "32")] #[test] fn test_size() { assert_size!(SetQuery, 40); assert_size!(SetResult, 40); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { assert_size!(SetQuery, 80); assert_size!(SetResult, 80); } #[test] fn test_simple() { let elem: Element = "" .parse() .unwrap(); let set = SetQuery::try_from(elem).unwrap(); assert_eq!(set.max, None); assert_eq!(set.after, None); assert_eq!(set.before, None); assert_eq!(set.index, None); let elem: Element = "" .parse() .unwrap(); let set = SetResult::try_from(elem).unwrap(); match set.first { Some(_) => panic!(), None => (), } assert_eq!(set.last, None); assert_eq!(set.count, None); } #[test] fn test_unknown() { let elem: Element = "" .parse() .unwrap(); let error = SetQuery::try_from(elem.clone()).unwrap_err(); let returned_elem = match error { FromElementError::Mismatch(elem) => elem, _ => panic!(), }; assert_eq!(elem, returned_elem); let elem: Element = "" .parse() .unwrap(); let error = SetResult::try_from(elem.clone()).unwrap_err(); let returned_elem = match error { FromElementError::Mismatch(elem) => elem, _ => panic!(), }; assert_eq!(elem, returned_elem); } #[test] fn test_invalid_child() { let elem: Element = "" .parse() .unwrap(); let error = SetQuery::try_from(elem).unwrap_err(); let message = match error { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; assert_eq!(message, "Unknown child in SetQuery element."); let elem: Element = "" .parse() .unwrap(); let error = SetResult::try_from(elem).unwrap_err(); let message = match error { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; assert_eq!(message, "Unknown child in SetResult element."); } #[test] fn test_serialise() { let elem: Element = "" .parse() .unwrap(); let rsm = SetQuery { max: None, after: None, before: None, index: None, }; let elem2 = rsm.into(); assert_eq!(elem, elem2); let elem: Element = "" .parse() .unwrap(); let rsm = SetResult { first: None, last: None, count: None, }; let elem2 = rsm.into(); assert_eq!(elem, elem2); } // TODO: This test is only ignored because and aren’t equal in // minidom, let’s fix that instead! #[test] #[ignore] fn test_serialise_empty_before() { let elem: Element = "" .parse() .unwrap(); let rsm = SetQuery { max: None, after: None, before: Some("".into()), index: 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 = SetResult::try_from(elem).unwrap(); let first = set.first.unwrap(); assert_eq!(first.item, "coucou"); assert_eq!(first.index, Some(4)); let set2 = SetResult { first: Some(First { item: String::from("coucou"), index: Some(4), }), last: None, count: None, }; let elem2 = set2.into(); assert_eq!(elem1, elem2); } }