// Copyright (c) 2017-2021 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 crate::data_forms::DataForm; use crate::forwarding::Forwarded; use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload}; use crate::message::MessagePayload; use crate::pubsub::NodeName; use crate::rsm::{SetQuery, SetResult}; generate_id!( /// An identifier matching a result message to the query requesting it. QueryId ); generate_element!( /// Starts a query to the archive. Query, "query", MAM, attributes: [ /// An optional identifier for matching forwarded messages to this /// query. queryid: Option = "queryid", /// Must be set to Some when querying a PubSub node’s archive. node: Option = "node" ], children: [ /// Used for filtering the results. form: Option = ("x", DATA_FORMS) => DataForm, /// Used for paging through results. set: Option = ("set", RSM) => SetQuery ] ); impl IqGetPayload for Query {} impl IqSetPayload for Query {} impl IqResultPayload for Query {} generate_element!( /// The wrapper around forwarded stanzas. Result_, "result", MAM, attributes: [ /// The stanza-id under which the archive stored this stanza. id: Required = "id", /// The same queryid as the one requested in the /// [query](struct.Query.html). queryid: Option = "queryid", ], children: [ /// The actual stanza being forwarded. forwarded: Required = ("forwarded", FORWARD) => Forwarded ] ); impl MessagePayload for Result_ {} generate_attribute!( /// True when the end of a MAM query has been reached. Complete, "complete", bool ); generate_element!( /// Notes the end of a page in a query. Fin, "fin", MAM, attributes: [ /// True when the end of a MAM query has been reached. complete: Default = "complete", ], children: [ /// Describes the current page, it should contain at least [first] /// (with an [index]) and [last], and generally [count]. /// /// [first]: ../rsm/struct.SetResult.html#structfield.first /// [index]: ../rsm/struct.SetResult.html#structfield.first_index /// [last]: ../rsm/struct.SetResult.html#structfield.last /// [count]: ../rsm/struct.SetResult.html#structfield.count set: Required = ("set", RSM) => SetResult ] ); impl IqResultPayload for Fin {} #[cfg(test)] mod tests { use super::*; use crate::util::error::Error; use minidom::Element; use std::convert::TryFrom; #[cfg(target_pointer_width = "32")] #[test] fn test_size() { assert_size!(QueryId, 12); assert_size!(Query, 116); assert_size!(Result_, 236); assert_size!(Complete, 1); assert_size!(Fin, 44); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { assert_size!(QueryId, 24); assert_size!(Query, 232); assert_size!(Result_, 456); assert_size!(Complete, 1); assert_size!(Fin, 88); } #[test] fn test_query() { let elem: Element = "".parse().unwrap(); Query::try_from(elem).unwrap(); } #[test] fn test_result() { #[cfg(not(feature = "component"))] let elem: Element = r#" Hail to thee "# .parse() .unwrap(); #[cfg(feature = "component")] let elem: Element = r#" Hail to thee "#.parse().unwrap(); Result_::try_from(elem).unwrap(); } #[test] fn test_fin() { let elem: Element = r#" 28482-98726-73623 09af3-cc343-b409f "# .parse() .unwrap(); Fin::try_from(elem).unwrap(); } #[test] fn test_query_x() { let elem: Element = r#" urn:xmpp:mam:2 juliet@capulet.lit "# .parse() .unwrap(); Query::try_from(elem).unwrap(); } #[test] fn test_query_x_set() { let elem: Element = r#" urn:xmpp:mam:2 2010-08-07T00:00:00Z 10 "# .parse() .unwrap(); Query::try_from(elem).unwrap(); } #[test] fn test_invalid_child() { let elem: Element = "" .parse() .unwrap(); let error = Query::try_from(elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), }; assert_eq!(message, "Unknown child in query element."); } #[test] fn test_serialise_empty() { let elem: Element = "".parse().unwrap(); let replace = Query { queryid: None, node: None, form: None, set: None, }; let elem2 = replace.into(); assert_eq!(elem, elem2); } #[test] fn test_serialize_query_with_form() { let reference: Element = "urn:xmpp:mam:2juliet@capulet.lit" .parse() .unwrap(); let elem: Element = "urn:xmpp:mam:2juliet@capulet.lit" .parse() .unwrap(); let form = DataForm::try_from(elem).unwrap(); let query = Query { queryid: None, node: None, set: None, form: Some(form), }; let serialized: Element = query.into(); assert_eq!(serialized, reference); } #[test] fn test_serialize_result() { let reference: Element = "" .parse() .unwrap(); let elem: Element = "" .parse() .unwrap(); let forwarded = Forwarded::try_from(elem).unwrap(); let result = Result_ { id: String::from("28482-98726-73623"), queryid: Some(QueryId(String::from("f27"))), forwarded: forwarded, }; let serialized: Element = result.into(); assert_eq!(serialized, reference); } #[test] fn test_serialize_fin() { let reference: Element = "28482-98726-7362309af3-cc343-b409f" .parse() .unwrap(); let elem: Element = "28482-98726-7362309af3-cc343-b409f" .parse() .unwrap(); let set = SetResult::try_from(elem).unwrap(); let fin = Fin { set: set, complete: Complete::default(), }; let serialized: Element = fin.into(); assert_eq!(serialized, reference); } }