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<Self> {
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<Self> {
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<Self, Self::Err> {
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()
}
}