serdect/
slice.rs

1//! Serialization primitives for slices.
2
3use core::fmt;
4
5use serde::de::{Error, Visitor};
6use serde::{Deserializer, Serialize, Serializer};
7
8#[cfg(feature = "alloc")]
9use ::{alloc::vec::Vec, serde::Deserialize};
10
11#[cfg(feature = "zeroize")]
12use zeroize::Zeroize;
13
14/// Serialize the given type as lower case hex when using human-readable
15/// formats or binary if the format is binary.
16pub fn serialize_hex_lower_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
17where
18    S: Serializer,
19    T: AsRef<[u8]>,
20{
21    if serializer.is_human_readable() {
22        crate::serialize_hex::<_, _, false>(value, serializer)
23    } else {
24        value.as_ref().serialize(serializer)
25    }
26}
27
28/// Serialize the given type as upper case hex when using human-readable
29/// formats or binary if the format is binary.
30pub fn serialize_hex_upper_or_bin<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
31where
32    S: Serializer,
33    T: AsRef<[u8]>,
34{
35    if serializer.is_human_readable() {
36        crate::serialize_hex::<_, _, true>(value, serializer)
37    } else {
38        value.as_ref().serialize(serializer)
39    }
40}
41
42/// Deserialize from hex when using human-readable formats or binary if the
43/// format is binary. Fails if the `buffer` is smaller then the resulting
44/// slice.
45pub fn deserialize_hex_or_bin<'de, D>(buffer: &mut [u8], deserializer: D) -> Result<&[u8], D::Error>
46where
47    D: Deserializer<'de>,
48{
49    if deserializer.is_human_readable() {
50        struct StrVisitor<'b>(&'b mut [u8]);
51
52        impl<'de, 'b> Visitor<'de> for StrVisitor<'b> {
53            type Value = &'b [u8];
54
55            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
56                write!(
57                    formatter,
58                    "a string with a maximum length of {}",
59                    self.0.len() * 2
60                )
61            }
62
63            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
64            where
65                E: Error,
66            {
67                // TODO: Map `base16ct::Error::InvalidLength` to `Error::invalid_length`.
68                base16ct::mixed::decode(v, self.0).map_err(E::custom)
69            }
70        }
71
72        deserializer.deserialize_str(StrVisitor(buffer))
73    } else {
74        struct SliceVisitor<'b>(&'b mut [u8]);
75
76        impl<'de, 'b> Visitor<'de> for SliceVisitor<'b> {
77            type Value = &'b [u8];
78
79            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
80                write!(
81                    formatter,
82                    "a slice with a maximum length of {}",
83                    self.0.len()
84                )
85            }
86
87            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
88            where
89                E: Error,
90            {
91                // Workaround for
92                // https://github.com/rust-lang/rfcs/blob/b1de05846d9bc5591d753f611ab8ee84a01fa500/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions
93                if v.len() <= self.0.len() {
94                    let buffer = &mut self.0[..v.len()];
95                    buffer.copy_from_slice(v);
96                    return Ok(buffer);
97                }
98
99                Err(E::invalid_length(v.len(), &self))
100            }
101
102            #[cfg(feature = "alloc")]
103            fn visit_byte_buf<E>(self, mut v: Vec<u8>) -> Result<Self::Value, E>
104            where
105                E: Error,
106            {
107                // Workaround for
108                // https://github.com/rust-lang/rfcs/blob/b1de05846d9bc5591d753f611ab8ee84a01fa500/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions
109                if v.len() <= self.0.len() {
110                    let buffer = &mut self.0[..v.len()];
111                    buffer.swap_with_slice(&mut v);
112                    return Ok(buffer);
113                }
114
115                Err(E::invalid_length(v.len(), &self))
116            }
117        }
118
119        deserializer.deserialize_byte_buf(SliceVisitor(buffer))
120    }
121}
122
123/// Deserialize from hex when using human-readable formats or binary if the
124/// format is binary.
125#[cfg(feature = "alloc")]
126pub fn deserialize_hex_or_bin_vec<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
127where
128    D: Deserializer<'de>,
129{
130    if deserializer.is_human_readable() {
131        struct StrVisitor;
132
133        impl<'de> Visitor<'de> for StrVisitor {
134            type Value = Vec<u8>;
135
136            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
137                write!(formatter, "a string")
138            }
139
140            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
141            where
142                E: Error,
143            {
144                base16ct::mixed::decode_vec(v).map_err(E::custom)
145            }
146        }
147
148        deserializer.deserialize_str(StrVisitor)
149    } else {
150        Vec::deserialize(deserializer)
151    }
152}
153
154/// [`HexOrBin`] serializer which uses lower case.
155#[cfg(feature = "alloc")]
156pub type HexLowerOrBin = HexOrBin<false>;
157
158/// [`HexOrBin`] serializer which uses upper case.
159#[cfg(feature = "alloc")]
160pub type HexUpperOrBin = HexOrBin<true>;
161
162/// Serializer/deserializer newtype which encodes bytes as either binary or hex.
163///
164/// Use hexadecimal with human-readable formats, or raw binary with binary formats.
165#[cfg(feature = "alloc")]
166#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
167pub struct HexOrBin<const UPPERCASE: bool>(pub Vec<u8>);
168
169#[cfg(feature = "alloc")]
170impl<const UPPERCASE: bool> AsRef<[u8]> for HexOrBin<UPPERCASE> {
171    fn as_ref(&self) -> &[u8] {
172        self.0.as_ref()
173    }
174}
175
176#[cfg(feature = "alloc")]
177impl<const UPPERCASE: bool> From<&[u8]> for HexOrBin<UPPERCASE> {
178    fn from(bytes: &[u8]) -> HexOrBin<UPPERCASE> {
179        Self(bytes.into())
180    }
181}
182
183#[cfg(feature = "alloc")]
184impl<const UPPERCASE: bool> From<Vec<u8>> for HexOrBin<UPPERCASE> {
185    fn from(vec: Vec<u8>) -> HexOrBin<UPPERCASE> {
186        Self(vec)
187    }
188}
189
190#[cfg(feature = "alloc")]
191impl<const UPPERCASE: bool> From<HexOrBin<UPPERCASE>> for Vec<u8> {
192    fn from(vec: HexOrBin<UPPERCASE>) -> Vec<u8> {
193        vec.0
194    }
195}
196
197#[cfg(feature = "alloc")]
198impl<const UPPERCASE: bool> Serialize for HexOrBin<UPPERCASE> {
199    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
200    where
201        S: Serializer,
202    {
203        if UPPERCASE {
204            serialize_hex_upper_or_bin(self, serializer)
205        } else {
206            serialize_hex_lower_or_bin(self, serializer)
207        }
208    }
209}
210
211#[cfg(feature = "alloc")]
212impl<'de, const UPPERCASE: bool> Deserialize<'de> for HexOrBin<UPPERCASE> {
213    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
214    where
215        D: Deserializer<'de>,
216    {
217        deserialize_hex_or_bin_vec(deserializer).map(Self)
218    }
219}
220
221#[cfg(all(feature = "alloc", feature = "zeroize"))]
222impl<const UPPERCASE: bool> Zeroize for HexOrBin<UPPERCASE> {
223    fn zeroize(&mut self) {
224        self.0.as_mut_slice().zeroize();
225    }
226}