serdect/
array.rs

1//! Serialization primitives for arrays.
2
3use core::fmt;
4
5use serde::de::{Error, SeqAccess, Visitor};
6use serde::ser::SerializeTuple;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9#[cfg(feature = "zeroize")]
10use zeroize::Zeroize;
11
12/// Serialize the given type as lower case hex when using human-readable
13/// formats or binary if the format is binary.
14pub fn serialize_hex_lower_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
15where
16    S: Serializer,
17    T: AsRef<[u8]>,
18{
19    if serializer.is_human_readable() {
20        crate::serialize_hex::<_, _, false>(value, serializer)
21    } else {
22        let mut seq = serializer.serialize_tuple(value.as_ref().len())?;
23
24        for byte in value.as_ref() {
25            seq.serialize_element(byte)?;
26        }
27
28        seq.end()
29    }
30}
31
32/// Serialize the given type as upper case hex when using human-readable
33/// formats or binary if the format is binary.
34pub fn serialize_hex_upper_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
35where
36    S: Serializer,
37    T: AsRef<[u8]>,
38{
39    if serializer.is_human_readable() {
40        crate::serialize_hex::<_, _, true>(value, serializer)
41    } else {
42        let mut seq = serializer.serialize_tuple(value.as_ref().len())?;
43
44        for byte in value.as_ref() {
45            seq.serialize_element(byte)?;
46        }
47
48        seq.end()
49    }
50}
51
52/// Deserialize from hex when using human-readable formats or binary if the
53/// format is binary. Fails if the `buffer` isn't the exact same size as the
54/// resulting array.
55pub fn deserialize_hex_or_bin<'de, D>(buffer: &mut [u8], deserializer: D) -> Result<(), D::Error>
56where
57    D: Deserializer<'de>,
58{
59    if deserializer.is_human_readable() {
60        struct StrVisitor<'b>(&'b mut [u8]);
61
62        impl<'de> Visitor<'de> for StrVisitor<'_> {
63            type Value = ();
64
65            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
66                write!(formatter, "a string of length {}", self.0.len() * 2)
67            }
68
69            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
70            where
71                E: Error,
72            {
73                if v.len() != self.0.len() * 2 {
74                    return Err(Error::invalid_length(v.len(), &self));
75                }
76
77                base16ct::mixed::decode(v, self.0).map_err(E::custom)?;
78
79                Ok(())
80            }
81        }
82
83        deserializer.deserialize_str(StrVisitor(buffer))
84    } else {
85        struct ArrayVisitor<'b>(&'b mut [u8]);
86
87        impl<'de> Visitor<'de> for ArrayVisitor<'_> {
88            type Value = ();
89
90            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
91                write!(formatter, "an array of length {}", self.0.len())
92            }
93
94            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
95            where
96                A: SeqAccess<'de>,
97            {
98                for (index, byte) in self.0.iter_mut().enumerate() {
99                    *byte = match seq.next_element()? {
100                        Some(byte) => byte,
101                        None => return Err(Error::invalid_length(index, &self)),
102                    };
103                }
104
105                Ok(())
106            }
107        }
108
109        deserializer.deserialize_tuple(buffer.len(), ArrayVisitor(buffer))
110    }
111}
112
113/// [`HexOrBin`] serializer which uses lower case.
114pub type HexLowerOrBin<const N: usize> = HexOrBin<N, false>;
115
116/// [`HexOrBin`] serializer which uses upper case.
117pub type HexUpperOrBin<const N: usize> = HexOrBin<N, true>;
118
119/// Serializer/deserializer newtype which encodes bytes as either binary or hex.
120///
121/// Use hexadecimal with human-readable formats, or raw binary with binary formats.
122#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
123pub struct HexOrBin<const N: usize, const UPPERCASE: bool>(pub [u8; N]);
124
125impl<const N: usize, const UPPERCASE: bool> Default for HexOrBin<N, UPPERCASE> {
126    fn default() -> Self {
127        Self([0; N])
128    }
129}
130
131impl<const N: usize, const UPPERCASE: bool> AsRef<[u8]> for HexOrBin<N, UPPERCASE> {
132    fn as_ref(&self) -> &[u8] {
133        self.0.as_ref()
134    }
135}
136
137impl<const N: usize, const UPPERCASE: bool> From<&[u8; N]> for HexOrBin<N, UPPERCASE> {
138    fn from(bytes: &[u8; N]) -> Self {
139        Self(*bytes)
140    }
141}
142
143impl<const N: usize, const UPPERCASE: bool> From<[u8; N]> for HexOrBin<N, UPPERCASE> {
144    fn from(bytes: [u8; N]) -> Self {
145        Self(bytes)
146    }
147}
148
149impl<const N: usize, const UPPERCASE: bool> From<HexOrBin<N, UPPERCASE>> for [u8; N] {
150    fn from(hex_or_bin: HexOrBin<N, UPPERCASE>) -> Self {
151        hex_or_bin.0
152    }
153}
154
155impl<const N: usize, const UPPERCASE: bool> Serialize for HexOrBin<N, UPPERCASE> {
156    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
157    where
158        S: Serializer,
159    {
160        if UPPERCASE {
161            serialize_hex_upper_or_bin(self, serializer)
162        } else {
163            serialize_hex_lower_or_bin(self, serializer)
164        }
165    }
166}
167
168impl<'de, const N: usize, const UPPERCASE: bool> Deserialize<'de> for HexOrBin<N, UPPERCASE> {
169    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
170    where
171        D: Deserializer<'de>,
172    {
173        let mut buffer = [0; N];
174        deserialize_hex_or_bin(&mut buffer, deserializer)?;
175
176        Ok(Self(buffer))
177    }
178}
179
180#[cfg(feature = "zeroize")]
181#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
182impl<const N: usize, const UPPERCASE: bool> Zeroize for HexOrBin<N, UPPERCASE> {
183    fn zeroize(&mut self) {
184        self.0.as_mut_slice().zeroize();
185    }
186}