serde_byte_array/
bytearray.rs

1use core::array::TryFromSliceError;
2use core::borrow::{Borrow, BorrowMut};
3use core::cmp::Ordering;
4use core::convert::TryInto;
5use core::fmt::{self, Debug};
6use core::hash::{Hash, Hasher};
7use core::mem;
8use core::ops::{Deref, DerefMut};
9
10use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
11use serde::ser::{Serialize, Serializer};
12
13/// Wrapper around `[u8; N]` to serialize and deserialize efficiently.
14///
15/// ```
16/// use std::collections::HashMap;
17/// use std::io;
18///
19/// use serde_byte_array::ByteArray;
20///
21/// fn deserialize_bytearrays() -> bincode::Result<()> {
22///     let example_data = [
23///         2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
24///         119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101
25///     ];
26///
27///     let map: HashMap<u32, ByteArray<3>> = bincode::deserialize(&example_data[..])?;
28///
29///     println!("{:?}", map);
30///
31///     Ok(())
32/// }
33/// #
34/// # fn main() {
35/// #     deserialize_bytearrays().unwrap();
36/// # }
37/// ```
38#[derive(Copy, Clone, Eq, Ord)]
39#[repr(transparent)]
40pub struct ByteArray<const N: usize> {
41    bytes: [u8; N],
42}
43
44impl<const N: usize> ByteArray<N> {
45    /// Transform an [array](https://doc.rust-lang.org/stable/std/primitive.array.html) to the equivalent `ByteArray`
46    pub const fn new(bytes: [u8; N]) -> Self {
47        Self { bytes }
48    }
49
50    /// Wrap existing bytes into a `ByteArray`
51    pub fn from<T: Into<[u8; N]>>(bytes: T) -> Self {
52        Self {
53            bytes: bytes.into(),
54        }
55    }
56
57    /// Return a slice containing all bytes.
58    pub const fn as_slice(&self) -> &[u8] {
59        &self.bytes
60    }
61
62    /// Unwraps the byte array underlying this `ByteArray`
63    pub const fn into_array(self) -> [u8; N] {
64        self.bytes
65    }
66}
67
68impl<const N: usize> From<[u8; N]> for ByteArray<N> {
69    fn from(bytes: [u8; N]) -> ByteArray<N> {
70        ByteArray { bytes }
71    }
72}
73
74impl<const N: usize> From<ByteArray<N>> for [u8; N] {
75    fn from(bytes: ByteArray<N>) -> [u8; N] {
76        bytes.bytes
77    }
78}
79
80impl<'a, const N: usize> From<&'a [u8; N]> for &'a ByteArray<N> {
81    fn from(bytes: &'a [u8; N]) -> &'a ByteArray<N> {
82        // Safety: #[repr(transparent)]
83        unsafe { mem::transmute::<&'a [u8; N], &'a ByteArray<N>>(bytes) }
84    }
85}
86
87impl<'a, const N: usize> From<&'a ByteArray<N>> for &'a [u8; N] {
88    fn from(bytes: &'a ByteArray<N>) -> &'a [u8; N] {
89        // Safety: #[repr(transparent)]
90        unsafe { mem::transmute::<&'a ByteArray<N>, &'a [u8; N]>(bytes) }
91    }
92}
93
94impl<'a, const N: usize> TryFrom<&'a [u8]> for ByteArray<N> {
95    type Error = TryFromSliceError;
96    fn try_from(bytes: &'a [u8]) -> Result<Self, TryFromSliceError> {
97        Ok(Self {
98            bytes: bytes.try_into()?,
99        })
100    }
101}
102
103impl<'a, const N: usize> TryFrom<&'a [u8]> for &'a ByteArray<N> {
104    type Error = TryFromSliceError;
105    fn try_from(bytes: &'a [u8]) -> Result<Self, TryFromSliceError> {
106        let tmp: &'a [u8; N] = bytes.try_into()?;
107        Ok(tmp.into())
108    }
109}
110
111impl<const N: usize> Debug for ByteArray<N> {
112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113        Debug::fmt(&self.bytes, f)
114    }
115}
116
117impl<const N: usize> Default for ByteArray<N> {
118    fn default() -> Self {
119        Self::new([Default::default(); N])
120    }
121}
122
123impl<const N: usize> AsRef<[u8; N]> for ByteArray<N> {
124    fn as_ref(&self) -> &[u8; N] {
125        &self.bytes
126    }
127}
128impl<const N: usize> AsMut<[u8; N]> for ByteArray<N> {
129    fn as_mut(&mut self) -> &mut [u8; N] {
130        &mut self.bytes
131    }
132}
133
134impl<const N: usize> AsRef<[u8]> for ByteArray<N> {
135    fn as_ref(&self) -> &[u8] {
136        &self.bytes
137    }
138}
139
140impl<const N: usize> AsMut<[u8]> for ByteArray<N> {
141    fn as_mut(&mut self) -> &mut [u8] {
142        &mut self.bytes
143    }
144}
145
146impl<const N: usize> Borrow<[u8; N]> for ByteArray<N> {
147    fn borrow(&self) -> &[u8; N] {
148        &self.bytes
149    }
150}
151impl<const N: usize> BorrowMut<[u8; N]> for ByteArray<N> {
152    fn borrow_mut(&mut self) -> &mut [u8; N] {
153        &mut self.bytes
154    }
155}
156
157impl<const N: usize> Borrow<[u8]> for ByteArray<N> {
158    fn borrow(&self) -> &[u8] {
159        &self.bytes
160    }
161}
162impl<const N: usize> BorrowMut<[u8]> for ByteArray<N> {
163    fn borrow_mut(&mut self) -> &mut [u8] {
164        &mut self.bytes
165    }
166}
167
168impl<const N: usize> Deref for ByteArray<N> {
169    type Target = [u8; N];
170
171    fn deref(&self) -> &Self::Target {
172        &self.bytes
173    }
174}
175
176impl<const N: usize> DerefMut for ByteArray<N> {
177    fn deref_mut(&mut self) -> &mut Self::Target {
178        &mut self.bytes
179    }
180}
181
182impl<Rhs, const N: usize> PartialEq<Rhs> for ByteArray<N>
183where
184    Rhs: ?Sized + Borrow<[u8; N]>,
185{
186    fn eq(&self, other: &Rhs) -> bool {
187        (**self).eq(other.borrow())
188    }
189}
190
191impl<Rhs, const N: usize> PartialOrd<Rhs> for ByteArray<N>
192where
193    Rhs: ?Sized + Borrow<[u8; N]>,
194{
195    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
196        (**self).partial_cmp(other.borrow())
197    }
198}
199
200impl<const N: usize> Hash for ByteArray<N> {
201    fn hash<H: Hasher>(&self, state: &mut H) {
202        self.bytes.hash(state);
203    }
204}
205
206impl<const N: usize> IntoIterator for ByteArray<N> {
207    type Item = u8;
208    type IntoIter = <[u8; N] as IntoIterator>::IntoIter;
209
210    fn into_iter(self) -> Self::IntoIter {
211        IntoIterator::into_iter(self.bytes)
212    }
213}
214
215impl<'a, const N: usize> IntoIterator for &'a ByteArray<N> {
216    type Item = &'a u8;
217    type IntoIter = <&'a [u8; N] as IntoIterator>::IntoIter;
218
219    fn into_iter(self) -> Self::IntoIter {
220        self.bytes.iter()
221    }
222}
223
224impl<'a, const N: usize> IntoIterator for &'a mut ByteArray<N> {
225    type Item = &'a mut u8;
226    type IntoIter = <&'a mut [u8; N] as IntoIterator>::IntoIter;
227
228    fn into_iter(self) -> Self::IntoIter {
229        self.bytes.iter_mut()
230    }
231}
232
233impl<const N: usize> Serialize for ByteArray<N> {
234    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
235    where
236        S: Serializer,
237    {
238        serializer.serialize_bytes(&self.bytes)
239    }
240}
241
242struct ByteArrayVisitor<const N: usize>;
243
244impl<'de, const N: usize> Visitor<'de> for ByteArrayVisitor<N> {
245    type Value = ByteArray<N>;
246
247    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
248        write!(formatter, "a byte array of length {}", N)
249    }
250
251    fn visit_seq<V>(self, mut seq: V) -> Result<ByteArray<N>, V::Error>
252    where
253        V: SeqAccess<'de>,
254    {
255        let mut bytes = [0; N];
256
257        for (idx, byte) in bytes.iter_mut().enumerate() {
258            *byte = seq
259                .next_element()?
260                .ok_or_else(|| V::Error::invalid_length(idx, &self))?;
261        }
262
263        Ok(ByteArray::from(bytes))
264    }
265
266    fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteArray<N>, E>
267    where
268        E: Error,
269    {
270        Ok(ByteArray {
271            bytes: v
272                .try_into()
273                .map_err(|_| E::invalid_length(v.len(), &self))?,
274        })
275    }
276
277    fn visit_str<E>(self, v: &str) -> Result<ByteArray<N>, E>
278    where
279        E: Error,
280    {
281        self.visit_bytes(v.as_bytes())
282    }
283}
284
285impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
286    fn deserialize<D>(deserializer: D) -> Result<ByteArray<N>, D::Error>
287    where
288        D: Deserializer<'de>,
289    {
290        deserializer.deserialize_bytes(ByteArrayVisitor::<N>)
291    }
292}
293
294struct ByteArrayRefVisitor<const N: usize>;
295
296impl<'de, const N: usize> Visitor<'de> for ByteArrayRefVisitor<N> {
297    type Value = &'de ByteArray<N>;
298
299    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
300        write!(formatter, "a byte array of length {}", N)
301    }
302
303    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<&'de ByteArray<N>, E>
304    where
305        E: Error,
306    {
307        let arr: &[u8; N] = v
308            .try_into()
309            .map_err(|_| E::invalid_length(v.len(), &self))?;
310        Ok(arr.into())
311    }
312
313    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<&'de ByteArray<N>, E>
314    where
315        E: Error,
316    {
317        self.visit_borrowed_bytes(v.as_bytes())
318    }
319}
320
321impl<'de, const N: usize> Deserialize<'de> for &'de ByteArray<N> {
322    fn deserialize<D>(deserializer: D) -> Result<&'de ByteArray<N>, D::Error>
323    where
324        D: Deserializer<'de>,
325    {
326        deserializer.deserialize_bytes(ByteArrayRefVisitor)
327    }
328}