diff options
Diffstat (limited to 'src/stanza/client/presence.rs')
-rw-r--r-- | src/stanza/client/presence.rs | 194 |
1 files changed, 186 insertions, 8 deletions
diff --git a/src/stanza/client/presence.rs b/src/stanza/client/presence.rs index 46194f3..bcb04d4 100644 --- a/src/stanza/client/presence.rs +++ b/src/stanza/client/presence.rs @@ -1,24 +1,77 @@ -use peanuts::element::{FromElement, IntoElement}; +use std::str::FromStr; + +use peanuts::{ + element::{FromElement, IntoElement}, + DeserializeError, Element, XML_NS, +}; use crate::JID; -use super::error::Error; +use super::{error::Error, XMLNS}; pub struct Presence { from: Option<JID>, id: Option<String>, to: Option<JID>, - r#type: PresenceType, + r#type: Option<PresenceType>, lang: Option<String>, // children show: Option<Show>, status: Option<Status>, priority: Option<Priority>, + // TODO: ##other + // other: Vec<Other>, errors: Vec<Error>, - // ##other - // content: Vec<Box<dyn AsElement>>, } +impl FromElement for Presence { + fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("presence")?; + element.check_namespace(XMLNS)?; + + let from = element.attribute_opt("from")?; + let id = element.attribute_opt("id")?; + let to = element.attribute_opt("to")?; + let r#type = element.attribute_opt("type")?; + let lang = element.attribute_opt_namespaced("lang", XML_NS)?; + + let show = element.child_opt()?; + let status = element.child_opt()?; + let priority = element.child_opt()?; + let errors = element.children()?; + + Ok(Presence { + from, + id, + to, + r#type, + lang, + show, + status, + priority, + errors, + }) + } +} + +impl IntoElement for Presence { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("presence", Some(XMLNS)) + .push_attribute_opt("from", self.from.clone()) + .push_attribute_opt("id", self.id.clone()) + .push_attribute_opt("to", self.to.clone()) + .push_attribute_opt("type", self.r#type) + .push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone()) + .push_child_opt(self.show) + .push_child_opt(self.status.clone()) + .push_child_opt(self.priority) + .push_children(self.errors.clone()) + } +} + +pub enum Other {} + +#[derive(Copy, Clone)] pub enum PresenceType { Error, Probe, @@ -29,6 +82,38 @@ pub enum PresenceType { Unsubscribed, } +impl FromStr for PresenceType { + type Err = DeserializeError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "error" => Ok(PresenceType::Error), + "probe" => Ok(PresenceType::Probe), + "subscribe" => Ok(PresenceType::Subscribe), + "subscribed" => Ok(PresenceType::Subscribed), + "unavailable" => Ok(PresenceType::Unavailable), + "unsubscribe" => Ok(PresenceType::Unsubscribe), + "unsubscribed" => Ok(PresenceType::Unsubscribed), + s => Err(DeserializeError::FromStr(s.to_string())), + } + } +} + +impl ToString for PresenceType { + fn to_string(&self) -> String { + match self { + PresenceType::Error => "error".to_string(), + PresenceType::Probe => "probe".to_string(), + PresenceType::Subscribe => "subscribe".to_string(), + PresenceType::Subscribed => "subscribed".to_string(), + PresenceType::Unavailable => "unavailable".to_string(), + PresenceType::Unsubscribe => "unsubscribe".to_string(), + PresenceType::Unsubscribed => "unsubscribed".to_string(), + } + } +} + +#[derive(Copy, Clone)] pub enum Show { Away, Chat, @@ -36,13 +121,106 @@ pub enum Show { Xa, } +impl FromElement for Show { + fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("show")?; + element.check_namespace(XMLNS)?; + + Ok(element.pop_value()?) + } +} + +impl FromStr for Show { + type Err = DeserializeError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "away" => Ok(Show::Away), + "chat" => Ok(Show::Chat), + "dnd" => Ok(Show::Dnd), + "xa" => Ok(Show::Xa), + s => Err(DeserializeError::FromStr(s.to_string())), + } + } +} + +impl IntoElement for Show { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("show", Some(XMLNS)).push_text(*self) + } +} + +impl ToString for Show { + fn to_string(&self) -> String { + match self { + Show::Away => "away".to_string(), + Show::Chat => "chat".to_string(), + Show::Dnd => "dnd".to_string(), + Show::Xa => "xa".to_string(), + } + } +} + +#[derive(Clone)] pub struct Status { lang: Option<String>, status: String1024, } -// minLength 1 maxLength 1024 -pub struct String1024(String); +impl FromElement for Status { + fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("status")?; + element.check_namespace(XMLNS)?; + + let lang = element.attribute_opt_namespaced("lang", XML_NS)?; + let status = element.pop_value()?; + + Ok(Status { lang, status }) + } +} + +impl IntoElement for Status { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("status", Some(XMLNS)) + .push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone()) + .push_text(self.status.clone()) + } +} + +// TODO: enforce? +/// minLength 1 maxLength 1024 +#[derive(Clone)] +pub struct String1024(pub String); + +impl FromStr for String1024 { + type Err = DeserializeError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(String1024(s.to_string())) + } +} + +impl ToString for String1024 { + fn to_string(&self) -> String { + self.0.clone() + } +} // xs:byte -pub struct Priority(u8); +#[derive(Clone, Copy)] +pub struct Priority(pub i8); + +impl FromElement for Priority { + fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("priority")?; + element.check_namespace(XMLNS)?; + + Ok(Priority(element.pop_value()?)) + } +} + +impl IntoElement for Priority { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("priority", Some(XMLNS)).push_text(self.0) + } +} |