use base64ct::Encoding;
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::Debug;
use std::ops::Deref;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct EmbeddedContent(Vec<u8>);
impl EmbeddedContent {
pub fn as_slice(&self) -> &[u8] {
self.0.as_slice()
}
}
impl Deref for EmbeddedContent {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.0.as_slice()
}
}
impl AsRef<[u8]> for EmbeddedContent {
fn as_ref(&self) -> &[u8] {
self.0.as_slice()
}
}
impl From<Vec<u8>> for EmbeddedContent {
fn from(v: Vec<u8>) -> Self {
Self(v)
}
}
impl From<EmbeddedContent> for Vec<u8> {
fn from(v: EmbeddedContent) -> Self {
v.0
}
}
impl TryFrom<String> for EmbeddedContent {
type Error = &'static str;
fn try_from(string: String) -> Result<Self, Self::Error> {
let mut bytes = string.into_bytes();
bytes.retain(|b| !(*b as char).is_ascii_whitespace());
let len = base64ct::Base64::decode_in_place(bytes.as_mut_slice())
.map(|slice| slice.len())
.map_err(|_| "invalid base64 data")?;
bytes.truncate(len);
Ok(Self(bytes))
}
}
impl<'de> Deserialize<'de> for EmbeddedContent {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
String::deserialize(deserializer)?
.try_into()
.map_err(D::Error::custom)
}
}
impl Serialize for EmbeddedContent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let bytes = self.0.as_slice();
let len = base64ct::Base64::encoded_len(bytes);
let mut output = vec![0u8; len];
let str = base64ct::Base64::encode(bytes, &mut output).unwrap();
serializer.serialize_str(str)
}
}
impl ToString for EmbeddedContent {
fn to_string(&self) -> String {
let bytes = self.0.as_slice();
let len = base64ct::Base64::encoded_len(bytes);
let mut output = vec![0u8; len];
let str = base64ct::Base64::encode(bytes, &mut output).unwrap();
str.into()
}
}