luct-core 0.2.0

Core types and parsers for certificate transparency
Documentation
use crate::utils::codec::{Codec, Decode, Encode};
use base64::{Engine, prelude::BASE64_STANDARD};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de, ser};
use std::{
    fmt,
    io::{Cursor, Write},
    ops::{Deref, DerefMut},
};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct Base64<T>(pub T);

impl<T> Deref for Base64<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for Base64<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T> From<T> for Base64<T> {
    fn from(value: T) -> Self {
        Self(value)
    }
}

impl AsRef<[u8]> for Base64<Vec<u8>> {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl Serialize for Base64<Vec<u8>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let encoded = BASE64_STANDARD.encode(&self.0);
        serializer.serialize_str(&encoded)
    }
}

struct Base64VecVisitor;

impl<'de> de::Visitor<'de> for Base64VecVisitor {
    type Value = Vec<u8>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "A string containing a base64 encoded value")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        self.visit_borrowed_str(v)
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        BASE64_STANDARD.decode(v).map_err(de::Error::custom)
    }
}

impl<'de> Deserialize<'de> for Base64<Vec<u8>> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        Ok(Base64(deserializer.deserialize_str(Base64VecVisitor)?))
    }
}

impl<T: Encode> Serialize for Base64<Codec<T>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut data = Cursor::new(vec![]);
        self.encode(&mut data).map_err(ser::Error::custom)?;
        data.flush().map_err(ser::Error::custom)?;

        let encoded = BASE64_STANDARD.encode(data.into_inner());
        serializer.serialize_str(&encoded)
    }
}

impl<'de, T: Decode> Deserialize<'de> for Base64<Codec<T>> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let encoded = <String>::deserialize(deserializer)?;
        let decoded = BASE64_STANDARD.decode(encoded).map_err(de::Error::custom)?;

        let data = Cursor::new(decoded);
        T::decode(data)
            .map_err(de::Error::custom)
            .map(|v| Self(Codec(v)))
    }
}