use std::str::FromStr; use jid::JID; use peanuts::{ element::{FromElement, IntoElement}, DeserializeError, Element, XML_NS, }; use super::{error::Error, XMLNS}; #[derive(Debug)] pub struct Presence { pub from: Option, pub id: Option, pub to: Option, pub r#type: Option, pub lang: Option, // children pub show: Option, pub status: Option, pub priority: Option, // TODO: ##other // other: Vec, pub errors: Vec, } impl FromElement for Presence { fn from_element(mut element: Element) -> peanuts::element::DeserializeResult { 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, Debug)] pub enum PresenceType { Error, Probe, Subscribe, Subscribed, Unavailable, Unsubscribe, Unsubscribed, } impl FromStr for PresenceType { type Err = DeserializeError; fn from_str(s: &str) -> Result { 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, Debug)] pub enum Show { Away, Chat, /// do not disturb Dnd, /// extended away Xa, } impl FromElement for Show { fn from_element(mut element: Element) -> peanuts::element::DeserializeResult { 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 { 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, Debug)] pub struct Status { pub lang: Option, pub status: String1024, } impl FromElement for Status { fn from_element(mut element: Element) -> peanuts::element::DeserializeResult { 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, Debug)] pub struct String1024(pub String); impl FromStr for String1024 { type Err = DeserializeError; fn from_str(s: &str) -> Result { Ok(String1024(s.to_string())) } } impl ToString for String1024 { fn to_string(&self) -> String { self.0.clone() } } // xs:byte #[derive(Clone, Copy, Debug)] pub struct Priority(pub i8); impl FromElement for Priority { fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult { 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) } }