use core::fmt;
use core::marker::PhantomData;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::common::{self, LengthCheck, SliceVisitor, StrIntoBufVisitor};
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;
pub fn serialize_hex_lower_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: AsRef<[u8]>,
{
common::serialize_hex_lower_or_bin(value, serializer)
}
pub fn serialize_hex_upper_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: AsRef<[u8]>,
{
common::serialize_hex_upper_or_bin(value, serializer)
}
struct ExactLength;
impl LengthCheck for ExactLength {
fn length_check(buffer_length: usize, data_length: usize) -> bool {
buffer_length == data_length
}
fn expecting(
formatter: &mut fmt::Formatter<'_>,
data_type: &str,
data_length: usize,
) -> fmt::Result {
write!(formatter, "{data_type} of length {data_length}")
}
}
pub fn deserialize_hex_or_bin<'de, D>(buffer: &mut [u8], deserializer: D) -> Result<&[u8], D::Error>
where
D: Deserializer<'de>,
{
if deserializer.is_human_readable() {
deserializer.deserialize_str(StrIntoBufVisitor::<ExactLength>(buffer, PhantomData))
} else {
deserializer.deserialize_byte_buf(SliceVisitor::<ExactLength>(buffer, PhantomData))
}
}
pub type HexLowerOrBin<const N: usize> = HexOrBin<N, false>;
pub type HexUpperOrBin<const N: usize> = HexOrBin<N, true>;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct HexOrBin<const N: usize, const UPPERCASE: bool>(pub [u8; N]);
impl<const N: usize, const UPPERCASE: bool> Default for HexOrBin<N, UPPERCASE> {
fn default() -> Self {
Self([0; N])
}
}
impl<const N: usize, const UPPERCASE: bool> AsRef<[u8]> for HexOrBin<N, UPPERCASE> {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<const N: usize, const UPPERCASE: bool> From<&[u8; N]> for HexOrBin<N, UPPERCASE> {
fn from(bytes: &[u8; N]) -> Self {
Self(*bytes)
}
}
impl<const N: usize, const UPPERCASE: bool> From<[u8; N]> for HexOrBin<N, UPPERCASE> {
fn from(bytes: [u8; N]) -> Self {
Self(bytes)
}
}
impl<const N: usize, const UPPERCASE: bool> From<HexOrBin<N, UPPERCASE>> for [u8; N] {
fn from(hex_or_bin: HexOrBin<N, UPPERCASE>) -> Self {
hex_or_bin.0
}
}
impl<const N: usize, const UPPERCASE: bool> Serialize for HexOrBin<N, UPPERCASE> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if UPPERCASE {
serialize_hex_upper_or_bin(self, serializer)
} else {
serialize_hex_lower_or_bin(self, serializer)
}
}
}
impl<'de, const N: usize, const UPPERCASE: bool> Deserialize<'de> for HexOrBin<N, UPPERCASE> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let mut buffer = [0; N];
deserialize_hex_or_bin(&mut buffer, deserializer)?;
Ok(Self(buffer))
}
}
#[cfg(feature = "zeroize")]
impl<const N: usize, const UPPERCASE: bool> Zeroize for HexOrBin<N, UPPERCASE> {
fn zeroize(&mut self) {
self.0.as_mut_slice().zeroize();
}
}