2017-04-29 22:14:34 +01:00
|
|
|
|
// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
|
|
|
|
|
//
|
|
|
|
|
|
// 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/.
|
|
|
|
|
|
|
2024-12-21 00:39:55 +01:00
|
|
|
|
use xso::{AsXml, FromXml};
|
|
|
|
|
|
|
2018-12-18 15:27:30 +01:00
|
|
|
|
use crate::ns;
|
2017-04-29 04:37:18 +01:00
|
|
|
|
|
2018-08-02 20:43:47 +02:00
|
|
|
|
/// Requests paging through a potentially big set of items (represented by an
|
|
|
|
|
|
/// UID).
|
2024-12-21 00:39:55 +01:00
|
|
|
|
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
|
|
|
|
|
|
#[xml(namespace = ns::RSM, name = "set")]
|
2018-08-02 20:35:15 +02:00
|
|
|
|
pub struct SetQuery {
|
|
|
|
|
|
/// Limit the number of items, or use the recipient’s defaults if None.
|
2024-12-21 00:39:55 +01:00
|
|
|
|
#[xml(extract(default, fields(text(type_ = usize))))]
|
2018-08-02 20:35:15 +02:00
|
|
|
|
pub max: Option<usize>,
|
|
|
|
|
|
|
|
|
|
|
|
/// The UID after which to give results, or if None it is the element
|
|
|
|
|
|
/// “before” the first item, effectively an index of negative one.
|
2024-12-21 00:39:55 +01:00
|
|
|
|
#[xml(extract(default, fields(text(type_ = String))))]
|
2017-04-29 04:37:18 +01:00
|
|
|
|
pub after: Option<String>,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
|
|
|
|
|
|
/// The UID before which to give results, or if None it starts with the
|
|
|
|
|
|
/// last page of the full set.
|
2024-12-21 00:39:55 +01:00
|
|
|
|
#[xml(extract(default, fields(text(type_ = String))))]
|
2017-04-29 04:37:18 +01:00
|
|
|
|
pub before: Option<String>,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
|
|
|
|
|
|
/// Numerical index of the page (deprecated).
|
2024-12-21 00:39:55 +01:00
|
|
|
|
#[xml(extract(default, fields(text(type_ = usize))))]
|
2017-04-29 04:37:18 +01:00
|
|
|
|
pub index: Option<usize>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-21 00:47:12 +01:00
|
|
|
|
/// 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<usize>,
|
|
|
|
|
|
|
2018-08-02 20:35:15 +02:00
|
|
|
|
/// The UID of the first item of the page.
|
2024-12-21 00:47:12 +01:00
|
|
|
|
#[xml(text)]
|
|
|
|
|
|
pub item: String,
|
|
|
|
|
|
}
|
2018-08-02 20:35:15 +02:00
|
|
|
|
|
2024-12-21 00:47:12 +01:00
|
|
|
|
/// 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<First>,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
|
|
|
|
|
|
/// The UID of the last item of the page.
|
2024-12-21 00:47:12 +01:00
|
|
|
|
#[xml(extract(default, fields(text(type_ = String))))]
|
2018-08-02 20:35:15 +02:00
|
|
|
|
pub last: Option<String>,
|
|
|
|
|
|
|
|
|
|
|
|
/// How many items there are in the full set (which may be approximate).
|
2024-12-21 00:47:12 +01:00
|
|
|
|
#[xml(extract(default, fields(text(type_ = usize))))]
|
2018-08-02 20:35:15 +02:00
|
|
|
|
pub count: Option<usize>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-04-29 04:37:18 +01:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
2017-05-06 20:14:45 +01:00
|
|
|
|
use super::*;
|
2024-12-21 00:47:12 +01:00
|
|
|
|
use minidom::Element;
|
|
|
|
|
|
use xso::error::{Error, FromElementError};
|
2017-04-29 04:37:18 +01:00
|
|
|
|
|
2018-10-28 13:10:48 +01:00
|
|
|
|
#[cfg(target_pointer_width = "32")]
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_size() {
|
|
|
|
|
|
assert_size!(SetQuery, 40);
|
|
|
|
|
|
assert_size!(SetResult, 40);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(target_pointer_width = "64")]
|
2018-10-26 14:26:16 +02:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_size() {
|
|
|
|
|
|
assert_size!(SetQuery, 80);
|
|
|
|
|
|
assert_size!(SetResult, 80);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-04-29 04:37:18 +01:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_simple() {
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let set = SetQuery::try_from(elem).unwrap();
|
|
|
|
|
|
assert_eq!(set.max, None);
|
2017-04-29 04:37:18 +01:00
|
|
|
|
assert_eq!(set.after, None);
|
|
|
|
|
|
assert_eq!(set.before, None);
|
2018-08-02 20:35:15 +02:00
|
|
|
|
assert_eq!(set.index, None);
|
|
|
|
|
|
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let set = SetResult::try_from(elem).unwrap();
|
2017-04-29 04:37:18 +01:00
|
|
|
|
match set.first {
|
|
|
|
|
|
Some(_) => panic!(),
|
|
|
|
|
|
None => (),
|
|
|
|
|
|
}
|
|
|
|
|
|
assert_eq!(set.last, None);
|
2018-08-02 20:35:15 +02:00
|
|
|
|
assert_eq!(set.count, None);
|
2017-04-29 04:37:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_unknown() {
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0'/>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2024-03-02 09:19:49 +01:00
|
|
|
|
let error = SetQuery::try_from(elem.clone()).unwrap_err();
|
|
|
|
|
|
let returned_elem = match error {
|
2024-06-21 16:27:43 +02:00
|
|
|
|
FromElementError::Mismatch(elem) => elem,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
_ => panic!(),
|
|
|
|
|
|
};
|
2024-03-02 09:19:49 +01:00
|
|
|
|
assert_eq!(elem, returned_elem);
|
2018-08-02 20:35:15 +02:00
|
|
|
|
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0'/>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2024-03-02 09:19:49 +01:00
|
|
|
|
let error = SetResult::try_from(elem.clone()).unwrap_err();
|
|
|
|
|
|
let returned_elem = match error {
|
2024-06-21 16:27:43 +02:00
|
|
|
|
FromElementError::Mismatch(elem) => elem,
|
2017-04-29 04:37:18 +01:00
|
|
|
|
_ => panic!(),
|
|
|
|
|
|
};
|
2024-03-02 09:19:49 +01:00
|
|
|
|
assert_eq!(elem, returned_elem);
|
2017-04-29 04:37:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_invalid_child() {
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'><coucou/></set>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let error = SetQuery::try_from(elem).unwrap_err();
|
|
|
|
|
|
let message = match error {
|
2024-06-21 16:27:43 +02:00
|
|
|
|
FromElementError::Invalid(Error::Other(string)) => string,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
_ => panic!(),
|
|
|
|
|
|
};
|
2024-12-21 00:39:55 +01:00
|
|
|
|
assert_eq!(message, "Unknown child in SetQuery element.");
|
2018-08-02 20:35:15 +02:00
|
|
|
|
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'><coucou/></set>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let error = SetResult::try_from(elem).unwrap_err();
|
2017-04-29 04:37:18 +01:00
|
|
|
|
let message = match error {
|
2024-06-21 16:27:43 +02:00
|
|
|
|
FromElementError::Invalid(Error::Other(string)) => string,
|
2017-04-29 04:37:18 +01:00
|
|
|
|
_ => panic!(),
|
|
|
|
|
|
};
|
2024-12-21 00:47:12 +01:00
|
|
|
|
assert_eq!(message, "Unknown child in SetResult element.");
|
2017-04-29 04:37:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_serialise() {
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let rsm = SetQuery {
|
|
|
|
|
|
max: None,
|
2017-04-29 04:37:18 +01:00
|
|
|
|
after: None,
|
|
|
|
|
|
before: None,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
index: None,
|
|
|
|
|
|
};
|
|
|
|
|
|
let elem2 = rsm.into();
|
|
|
|
|
|
assert_eq!(elem, elem2);
|
|
|
|
|
|
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'/>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let rsm = SetResult {
|
2017-04-29 04:37:18 +01:00
|
|
|
|
first: None,
|
|
|
|
|
|
last: None,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
count: None,
|
2017-04-29 04:37:18 +01:00
|
|
|
|
};
|
2017-05-23 23:31:33 +01:00
|
|
|
|
let elem2 = rsm.into();
|
2017-04-29 04:37:18 +01:00
|
|
|
|
assert_eq!(elem, elem2);
|
|
|
|
|
|
}
|
2017-05-21 15:41:16 +01:00
|
|
|
|
|
2024-12-21 00:39:55 +01:00
|
|
|
|
// TODO: This test is only ignored because <before/> and <before></before> aren’t equal in
|
|
|
|
|
|
// minidom, let’s fix that instead!
|
2024-02-06 00:49:37 +01:00
|
|
|
|
#[test]
|
2024-12-21 00:39:55 +01:00
|
|
|
|
#[ignore]
|
2024-02-06 00:49:37 +01:00
|
|
|
|
fn test_serialise_empty_before() {
|
|
|
|
|
|
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'><before/></set>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
let rsm = SetQuery {
|
|
|
|
|
|
max: None,
|
|
|
|
|
|
after: None,
|
|
|
|
|
|
before: Some("".into()),
|
|
|
|
|
|
index: None,
|
|
|
|
|
|
};
|
|
|
|
|
|
let elem2 = rsm.into();
|
|
|
|
|
|
assert_eq!(elem, elem2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-05-21 15:41:16 +01:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_first_index() {
|
2018-12-18 15:32:05 +01:00
|
|
|
|
let elem: Element =
|
|
|
|
|
|
"<set xmlns='http://jabber.org/protocol/rsm'><first index='4'>coucou</first></set>"
|
|
|
|
|
|
.parse()
|
|
|
|
|
|
.unwrap();
|
2017-05-23 23:31:33 +01:00
|
|
|
|
let elem1 = elem.clone();
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let set = SetResult::try_from(elem).unwrap();
|
2024-12-21 00:47:12 +01:00
|
|
|
|
let first = set.first.unwrap();
|
|
|
|
|
|
assert_eq!(first.item, "coucou");
|
|
|
|
|
|
assert_eq!(first.index, Some(4));
|
2017-05-21 15:41:16 +01:00
|
|
|
|
|
2018-08-02 20:35:15 +02:00
|
|
|
|
let set2 = SetResult {
|
2024-12-21 00:47:12 +01:00
|
|
|
|
first: Some(First {
|
|
|
|
|
|
item: String::from("coucou"),
|
|
|
|
|
|
index: Some(4),
|
|
|
|
|
|
}),
|
2017-05-21 15:41:16 +01:00
|
|
|
|
last: None,
|
2018-08-02 20:35:15 +02:00
|
|
|
|
count: None,
|
2017-05-21 15:41:16 +01:00
|
|
|
|
};
|
2017-05-23 23:31:33 +01:00
|
|
|
|
let elem2 = set2.into();
|
2019-11-29 14:33:17 +01:00
|
|
|
|
assert_eq!(elem1, elem2);
|
2017-05-21 15:41:16 +01:00
|
|
|
|
}
|
2017-04-29 04:37:18 +01:00
|
|
|
|
}
|