use std::{convert::Infallible, str::FromStr}; use peanuts::{ element::{FromElement, IntoElement}, Element, }; pub const XMLNS: &str = "urn:xmpp:hashes:2"; #[derive(Debug, Clone)] pub struct Hash { pub algo: Algo, pub hash: String, } impl FromElement for Hash { fn from_element(mut element: Element) -> peanuts::element::DeserializeResult { element.check_name("hash")?; element.check_namespace(XMLNS)?; let algo = element.attribute("algo")?; let hash = element.pop_value_opt()?.unwrap_or_default(); Ok(Self { algo, hash }) } } impl IntoElement for Hash { fn builder(&self) -> peanuts::element::ElementBuilder { let builder = Element::builder("hash", Some(XMLNS)).push_attribute("algo", self.algo.clone()); // TODO: AAAAAAAAAAAAAAAAAAAAAA if self.hash.is_empty() { builder } else { builder.push_text(self.hash.clone()) } } } #[derive(Debug, Clone)] pub struct HashUsed { algo: Algo, } impl FromElement for HashUsed { fn from_element(mut element: Element) -> peanuts::element::DeserializeResult { element.check_name("hash-used")?; element.check_namespace(XMLNS)?; let algo = element.attribute("algo")?; Ok(Self { algo }) } } impl IntoElement for HashUsed { fn builder(&self) -> peanuts::element::ElementBuilder { Element::builder("hash-used", Some(XMLNS)).push_attribute("algo", self.algo.clone()) } } #[derive(Debug, Clone)] pub enum Algo { MD5, SHA1, SHA224, SHA256, SHA384, SHA512, SHA3224, SHA3256, SHA3384, SHA3512, BLAKE2b160, BLAKE2b256, BLAKE2b384, BLAKE2b512, Other(String), } impl FromStr for Algo { type Err = Infallible; fn from_str(s: &str) -> Result { match s { "md5" => Ok(Self::MD5), "sha-1" => Ok(Self::SHA1), "sha-224" => Ok(Self::SHA224), "sha-256" => Ok(Self::SHA256), "sha-384" => Ok(Self::SHA384), "sha-512" => Ok(Self::SHA512), "sha3-224" => Ok(Self::SHA3224), "sha3-256" => Ok(Self::SHA3256), "sha3-384" => Ok(Self::SHA3384), "sha3-512" => Ok(Self::SHA3512), "blake2b-160" => Ok(Self::BLAKE2b160), "blake2b-256" => Ok(Self::BLAKE2b256), "blake2b-384" => Ok(Self::BLAKE2b384), "blake2b-512" => Ok(Self::BLAKE2b512), s => Ok(Self::Other(s.to_owned())), } } } impl ToString for Algo { fn to_string(&self) -> String { match self { Algo::MD5 => "md5", Algo::SHA1 => "sha-1", Algo::SHA224 => "sha-224", Algo::SHA256 => "sha-256", Algo::SHA384 => "sha-384", Algo::SHA512 => "sha-512", Algo::SHA3224 => "sha3-224", Algo::SHA3256 => "sha3-256", Algo::SHA3384 => "sha3-384", Algo::SHA3512 => "sha3-512", Algo::BLAKE2b160 => "blake2b-160", Algo::BLAKE2b256 => "blake2b-256", Algo::BLAKE2b384 => "blake2b-384", Algo::BLAKE2b512 => "blake2b-512", Algo::Other(s) => s, } .to_owned() } }