aboutsummaryrefslogblamecommitdiffstats
path: root/stanza/src/xep_0300.rs
blob: 71a2c36c2a5429b8d2ce6cd86373a3068d87d706 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                                             


                                        
            





                                            

                     






































































                                                                                            
                          











































                                                     
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()
    }
}