use std::collections::{HashMap, HashSet}; use peanuts::{ element::{Content, FromElement, IntoElement, Name, NamespaceDeclaration}, Element, }; pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-tls"; #[derive(Debug)] pub struct StartTls { pub required: bool, } impl IntoElement for StartTls { fn into_element(&self) -> peanuts::Element { let content; if self.required == true { let element = Content::Element(Element { name: Name { namespace: Some(XMLNS.to_string()), local_name: "required".to_string(), }, namespace_declarations: HashSet::new(), attributes: HashMap::new(), content: Vec::new(), }); content = vec![element]; } else { content = Vec::new(); } let mut namespace_declarations = HashSet::new(); namespace_declarations.insert(NamespaceDeclaration { prefix: None, namespace: XMLNS.to_string(), }); Element { name: Name { namespace: Some(XMLNS.to_string()), local_name: "starttls".to_string(), }, namespace_declarations, attributes: HashMap::new(), content, } } } impl FromElement for StartTls { fn from_element(element: peanuts::Element) -> peanuts::Result { let Name { namespace, local_name, } = element.name; if namespace.as_deref() == Some(XMLNS) && &local_name == "starttls" { let mut required = false; if element.content.len() == 1 { match element.content.first().unwrap() { Content::Element(element) => { let Name { namespace, local_name, } = &element.name; if namespace.as_deref() == Some(XMLNS) && local_name == "required" { required = true } else { return Err(peanuts::Error::UnexpectedElement(element.name.clone())); } } c => return Err(peanuts::Error::UnexpectedContent((*c).clone())), } } else { return Err(peanuts::Error::UnexpectedNumberOfContents( element.content.len(), )); } return Ok(StartTls { required }); } else { return Err(peanuts::Error::IncorrectName(Name { namespace, local_name, })); } } } #[derive(Debug)] pub struct Proceed; impl IntoElement for Proceed { fn into_element(&self) -> Element { let mut namespace_declarations = HashSet::new(); namespace_declarations.insert(NamespaceDeclaration { prefix: None, namespace: XMLNS.to_string(), }); Element { name: Name { namespace: Some(XMLNS.to_string()), local_name: "proceed".to_string(), }, namespace_declarations, attributes: HashMap::new(), content: Vec::new(), } } } impl FromElement for Proceed { fn from_element(element: Element) -> peanuts::Result { let Name { namespace, local_name, } = element.name; if namespace.as_deref() == Some(XMLNS) && &local_name == "proceed" { return Ok(Proceed); } else { return Err(peanuts::Error::IncorrectName(Name { namespace, local_name, })); } } } pub struct Failure; impl IntoElement for Failure { fn into_element(&self) -> Element { let mut namespace_declarations = HashSet::new(); namespace_declarations.insert(NamespaceDeclaration { prefix: None, namespace: XMLNS.to_string(), }); Element { name: Name { namespace: Some(XMLNS.to_string()), local_name: "failure".to_string(), }, namespace_declarations, attributes: HashMap::new(), content: Vec::new(), } } } impl FromElement for Failure { fn from_element(element: Element) -> peanuts::Result { let Name { namespace, local_name, } = element.name; if namespace.as_deref() == Some(XMLNS) && &local_name == "failure" { return Ok(Failure); } else { return Err(peanuts::Error::IncorrectName(Name { namespace, local_name, })); } } }