use crate::crypto::digest::SALT_BYTES;
use crate::crypto::key::NONCE_BYTES;
use crate::error::{Error, Result};
use serde::de::{SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::result::Result as StdResult;
pub(crate) trait Compatible {
fn from_slice(bytes: &[u8]) -> Result<Self>
where
Self: Sized;
}
macro_rules! compat_type {
( $(#[$meta:meta])* $name:ident($bytes:expr_2021); ) => (
$(#[$meta])*
#[derive(Clone, Eq, PartialEq)]
pub(crate) struct $name(pub(crate) [u8; $bytes]);
impl Default for $name {
fn default() -> Self {
$name([0; $bytes])
}
}
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for b in self.0 {
write!(f, "{:02x}", b)?;
}
Ok(())
}
}
impl Compatible for $name {
fn from_slice(bytes: &[u8]) -> Result<Self> {
if bytes.len() != $bytes {
return Err(Error::InvalidArgument(format!("invalid {}, expected {} bytes, found {}", stringify!($name), $bytes, bytes.len())));
}
let mut x = Self::default();
x.0.as_mut_slice().copy_from_slice(bytes);
Ok(x)
}
}
impl Serialize for $name {
fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0)
}
}
impl<'de> Deserialize<'de> for $name {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
struct MyVisitor;
impl<'de> Visitor<'de> for MyVisitor {
type Value = $name;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}", stringify!($name))
}
fn visit_seq<V: SeqAccess<'de>>(self, mut visitor: V) -> StdResult<Self::Value, V::Error> {
let mut res = Self::Value::default();
for (i, b) in res.0.iter_mut().enumerate() {
match visitor.next_element::<u8>()? {
Some(vb) => *b = vb,
None => return Err(serde::de::Error::invalid_length(i, &self)),
}
}
if visitor.next_element::<u8>()?.is_some() {
return Err(serde::de::Error::invalid_length($bytes + 1, &self));
}
Ok(res)
}
fn visit_bytes<E: serde::de::Error>(self, v: &[u8]) -> StdResult<Self::Value, E> {
Self::Value::from_slice(v).map_err(|_| serde::de::Error::invalid_length(v.len(), &self))
}
}
deserializer.deserialize_bytes(MyVisitor)
}
}
);
}
compat_type! { Salt(SALT_BYTES); }
compat_type! { Nonce(NONCE_BYTES); }