Skip to main content

serdect/
array.rs

1//! Serialization primitives for arrays.
2
3// Unfortunately, we currently cannot tell `serde` in a uniform fashion that we are serializing
4// a fixed-size byte array.
5// See https://github.com/serde-rs/serde/issues/2120 for the discussion.
6// Therefore we have to fall back to the slice methods,
7// which will add the size information in the binary formats.
8// The only difference is that for the arrays we require the size of the data
9// to be exactly equal to the size of the buffer during deserialization,
10// while for slices the buffer can be larger than the deserialized data.
11
12use core::fmt;
13use core::marker::PhantomData;
14
15use serde::{Deserialize, Deserializer, Serialize, Serializer};
16
17use crate::common::{self, LengthCheck, SliceVisitor, StrIntoBufVisitor};
18
19#[cfg(feature = "zeroize")]
20use zeroize::Zeroize;
21
22/// Serialize the given type as lower case hex when using human-readable
23/// formats or binary if the format is binary.
24pub fn serialize_hex_lower_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
25where
26    S: Serializer,
27    T: AsRef<[u8]>,
28{
29    common::serialize_hex_lower_or_bin(value, serializer)
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    common::serialize_hex_upper_or_bin(value, serializer)
40}
41
42struct ExactLength;
43
44impl LengthCheck for ExactLength {
45    fn length_check(buffer_length: usize, data_length: usize) -> bool {
46        buffer_length == data_length
47    }
48    fn expecting(
49        formatter: &mut fmt::Formatter<'_>,
50        data_type: &str,
51        data_length: usize,
52    ) -> fmt::Result {
53        write!(formatter, "{data_type} of length {data_length}")
54    }
55}
56
57/// Deserialize from hex when using human-readable formats or binary if the
58/// format is binary. Fails if the `buffer` isn't the exact same size as the
59/// resulting array.
60pub fn deserialize_hex_or_bin<'de, D>(buffer: &mut [u8], deserializer: D) -> Result<&[u8], D::Error>
61where
62    D: Deserializer<'de>,
63{
64    if deserializer.is_human_readable() {
65        deserializer.deserialize_str(StrIntoBufVisitor::<ExactLength>(buffer, PhantomData))
66    } else {
67        deserializer.deserialize_byte_buf(SliceVisitor::<ExactLength>(buffer, PhantomData))
68    }
69}
70
71/// [`HexOrBin`] serializer which uses lower case.
72pub type HexLowerOrBin<const N: usize> = HexOrBin<N, false>;
73
74/// [`HexOrBin`] serializer which uses upper case.
75pub type HexUpperOrBin<const N: usize> = HexOrBin<N, true>;
76
77/// Serializer/deserializer newtype which encodes bytes as either binary or hex.
78///
79/// Use hexadecimal with human-readable formats, or raw binary with binary formats.
80#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
81pub struct HexOrBin<const N: usize, const UPPERCASE: bool>(pub [u8; N]);
82
83impl<const N: usize, const UPPERCASE: bool> Default for HexOrBin<N, UPPERCASE> {
84    fn default() -> Self {
85        Self([0; N])
86    }
87}
88
89impl<const N: usize, const UPPERCASE: bool> AsRef<[u8]> for HexOrBin<N, UPPERCASE> {
90    fn as_ref(&self) -> &[u8] {
91        self.0.as_ref()
92    }
93}
94
95impl<const N: usize, const UPPERCASE: bool> From<&[u8; N]> for HexOrBin<N, UPPERCASE> {
96    fn from(bytes: &[u8; N]) -> Self {
97        Self(*bytes)
98    }
99}
100
101impl<const N: usize, const UPPERCASE: bool> From<[u8; N]> for HexOrBin<N, UPPERCASE> {
102    fn from(bytes: [u8; N]) -> Self {
103        Self(bytes)
104    }
105}
106
107impl<const N: usize, const UPPERCASE: bool> From<HexOrBin<N, UPPERCASE>> for [u8; N] {
108    fn from(hex_or_bin: HexOrBin<N, UPPERCASE>) -> Self {
109        hex_or_bin.0
110    }
111}
112
113impl<const N: usize, const UPPERCASE: bool> Serialize for HexOrBin<N, UPPERCASE> {
114    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
115    where
116        S: Serializer,
117    {
118        if UPPERCASE {
119            serialize_hex_upper_or_bin(self, serializer)
120        } else {
121            serialize_hex_lower_or_bin(self, serializer)
122        }
123    }
124}
125
126impl<'de, const N: usize, const UPPERCASE: bool> Deserialize<'de> for HexOrBin<N, UPPERCASE> {
127    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
128    where
129        D: Deserializer<'de>,
130    {
131        let mut buffer = [0; N];
132        deserialize_hex_or_bin(&mut buffer, deserializer)?;
133
134        Ok(Self(buffer))
135    }
136}
137
138#[cfg(feature = "zeroize")]
139impl<const N: usize, const UPPERCASE: bool> Zeroize for HexOrBin<N, UPPERCASE> {
140    fn zeroize(&mut self) {
141        self.0.as_mut_slice().zeroize();
142    }
143}