roster: Make Group a proper struct.

This commit is contained in:
Emmanuel Gil Peyrot 2017-07-29 05:36:59 +01:00
parent 5388696b95
commit 6ec1e46953
2 changed files with 33 additions and 7 deletions

View file

@ -144,6 +144,28 @@ macro_rules! generate_id {
); );
} }
macro_rules! generate_elem_id {
($elem:ident, $name:tt, $ns:expr) => (
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct $elem(pub String);
impl FromStr for $elem {
type Err = Error;
fn from_str(s: &str) -> Result<$elem, Error> {
// TODO: add a way to parse that differently when needed.
Ok($elem(String::from(s)))
}
}
impl From<$elem> for Element {
fn from(elem: $elem) -> Element {
Element::builder($name)
.ns($ns)
.append(elem.0)
.build()
}
}
);
}
/// Error type returned by every parser on failure. /// Error type returned by every parser on failure.
pub mod error; pub mod error;
/// XML namespace definitions used through XMPP. /// XML namespace definitions used through XMPP.

View file

@ -13,7 +13,7 @@ use jid::Jid;
use error::Error; use error::Error;
use ns; use ns;
type Group = String; generate_elem_id!(Group, "group", ns::ROSTER);
generate_attribute!(Subscription, "subscription", { generate_attribute!(Subscription, "subscription", {
None => "none", None => "none",
@ -52,7 +52,11 @@ impl TryFrom<Element> for Item {
for _ in child.children() { for _ in child.children() {
return Err(Error::ParseError("Roster item group cant have children.")); return Err(Error::ParseError("Roster item group cant have children."));
} }
item.groups.push(child.text()); for _ in child.attrs() {
return Err(Error::ParseError("Roster item group cant have attributes."));
}
let group = Group(child.text());
item.groups.push(group);
} }
Ok(item) Ok(item)
} }
@ -65,7 +69,7 @@ impl From<Item> for Element {
.attr("jid", String::from(item.jid)) .attr("jid", String::from(item.jid))
.attr("name", item.name) .attr("name", item.name)
.attr("subscription", item.subscription) .attr("subscription", item.subscription)
.append(item.groups.into_iter().map(|group| Element::builder("group").ns(ns::ROSTER).append(group)).collect::<Vec<_>>()) .append(item.groups)
.build() .build()
} }
} }
@ -163,7 +167,7 @@ mod tests {
assert_eq!(roster.items[0].jid, Jid::from_str("romeo@example.net").unwrap()); assert_eq!(roster.items[0].jid, Jid::from_str("romeo@example.net").unwrap());
assert_eq!(roster.items[0].name, Some(String::from("Romeo"))); assert_eq!(roster.items[0].name, Some(String::from("Romeo")));
assert_eq!(roster.items[0].subscription, Some(Subscription::Both)); assert_eq!(roster.items[0].subscription, Some(Subscription::Both));
assert_eq!(roster.items[0].groups, vec!(String::from("Friends"))); assert_eq!(roster.items[0].groups, vec!(Group::from_str("Friends").unwrap()));
} }
#[test] #[test]
@ -183,8 +187,8 @@ mod tests {
assert_eq!(roster.items[0].jid, Jid::from_str("test@example.org").unwrap()); assert_eq!(roster.items[0].jid, Jid::from_str("test@example.org").unwrap());
assert_eq!(roster.items[0].name, None); assert_eq!(roster.items[0].name, None);
assert_eq!(roster.items[0].groups.len(), 2); assert_eq!(roster.items[0].groups.len(), 2);
assert_eq!(roster.items[0].groups[0], String::from("A")); assert_eq!(roster.items[0].groups[0], Group::from_str("A").unwrap());
assert_eq!(roster.items[0].groups[1], String::from("B")); assert_eq!(roster.items[0].groups[1], Group::from_str("B").unwrap());
let elem2 = roster.into(); let elem2 = roster.into();
assert_eq!(elem1, elem2); assert_eq!(elem1, elem2);
} }
@ -210,7 +214,7 @@ mod tests {
assert_eq!(roster.items[0].jid, Jid::from_str("nurse@example.com").unwrap()); assert_eq!(roster.items[0].jid, Jid::from_str("nurse@example.com").unwrap());
assert_eq!(roster.items[0].name, Some(String::from("Nurse"))); assert_eq!(roster.items[0].name, Some(String::from("Nurse")));
assert_eq!(roster.items[0].groups.len(), 1); assert_eq!(roster.items[0].groups.len(), 1);
assert_eq!(roster.items[0].groups[0], String::from("Servants")); assert_eq!(roster.items[0].groups[0], Group::from_str("Servants").unwrap());
let elem: Element = r#" let elem: Element = r#"
<query xmlns='jabber:iq:roster'> <query xmlns='jabber:iq:roster'>