1use serde::ser::SerializeTupleStruct;
2use serde::Serialize;
3use serde::Serializer;
4
5use core::convert::TryInto;
6use core::fmt;
7use serde::Deserializer;
8use serde::Deserialize;
9use serde::de;
10
11#[repr(transparent)]
15pub struct FixedSizeByteArray<const N: usize> {
16 inner: FixedSizeByteArrayInner<N>,
17}
18
19impl<const N: usize> From<[u8; N]> for FixedSizeByteArray<N> {
20 fn from(array: [u8; N]) -> FixedSizeByteArray<N> {
21 FixedSizeByteArray {
22 inner: FixedSizeByteArrayInner {
23 array,
24 },
25 }
26 }
27}
28
29impl<const N: usize> FixedSizeByteArray<N> {
30 pub fn into_inner(self) -> [u8; N] {
32 self.inner.array
33 }
34}
35
36#[repr(transparent)]
37struct FixedSizeByteArrayInner<const N: usize> {
38 array: [u8; N],
39}
40
41pub static TOKEN: &str = "$postcard::private::FixedSizeByteArray";
42
43impl<const N: usize> Serialize for FixedSizeByteArray<N> {
44 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45 where
46 S: Serializer,
47 {
48 let mut s = serializer.serialize_tuple_struct(TOKEN, 1)?;
49 s.serialize_field(&self.inner)?;
50 s.end()
51 }
52}
53
54impl<const N: usize> Serialize for FixedSizeByteArrayInner<N> {
55 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
56 where
57 S: Serializer,
58 {
59 serializer.serialize_bytes(&self.array)
60 }
61}
62
63impl<'de, const N: usize> Deserialize<'de> for FixedSizeByteArray<N> {
64 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
65 where
66 D: Deserializer<'de>,
67 {
68 struct Visitor<const N: usize>;
69
70 impl<'de, const N: usize> de::Visitor<'de> for Visitor<N> {
71 type Value = FixedSizeByteArray<N>;
72
73 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
74 write!(formatter, "byte array of length {}", N)
75 }
76
77 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
78 where
79 E: de::Error,
80 {
81 let array: [u8; N] = match v.try_into() {
82 Ok(a) => a,
83 Err(_) => return Err(de::Error::invalid_length(v.len(), &self)),
84 };
85 Ok(FixedSizeByteArray::from(array))
86 }
87 }
88
89 deserializer.deserialize_tuple_struct(TOKEN, N, Visitor)
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use crate::Error;
96 use super::FixedSizeByteArray;
97
98 #[test]
99 fn test_byte_array_serialize() {
100 let empty = FixedSizeByteArray::from([]);
101 let mut buf = [0; 32];
102 let serialized = crate::to_slice(&empty, &mut buf).unwrap();
103 assert_eq!(serialized, &[]);
104
105 let single = FixedSizeByteArray::from([0x12]);
106 let mut buf = [0; 32];
107 let serialized = crate::to_slice(&single, &mut buf).unwrap();
108 assert_eq!(serialized, &[0x12]);
109
110 let five_bytes = FixedSizeByteArray::from([0x12, 0x34, 0x56, 0x78, 0x90]);
111 let mut buf = [0; 32];
112 let serialized = crate::to_slice(&five_bytes, &mut buf).unwrap();
113 assert_eq!(serialized, &[0x12, 0x34, 0x56, 0x78, 0x90]);
114 }
115
116 #[test]
117 fn test_byte_array_deserialize() {
118 let deserialized: FixedSizeByteArray<0> = crate::from_bytes(&[]).unwrap();
119 assert_eq!(deserialized.into_inner(), []);
120
121 let deserialized: FixedSizeByteArray<0> = crate::from_bytes(&[0x12]).unwrap();
122 assert_eq!(deserialized.into_inner(), []);
123
124 let deserialized: FixedSizeByteArray<1> = crate::from_bytes(&[0x12]).unwrap();
125 assert_eq!(deserialized.into_inner(), [0x12]);
126
127 let deserialized: FixedSizeByteArray<5> = crate::from_bytes(&[0x12, 0x34, 0x56, 0x78, 0x90]).unwrap();
128 assert_eq!(deserialized.into_inner(), [0x12, 0x34, 0x56, 0x78, 0x90]);
129 }
130
131 #[test]
132 fn test_byte_array_deserialize_error() {
133 let result: Result<FixedSizeByteArray<1>, _> = crate::from_bytes(&[]);
134 assert_eq!(result.err().unwrap(), Error::DeserializeUnexpectedEnd);
135
136 let result: Result<FixedSizeByteArray<8>, _> = crate::from_bytes(&[0x12]);
137 assert_eq!(result.err().unwrap(), Error::DeserializeUnexpectedEnd);
138
139 let result: Result<FixedSizeByteArray<8>, _> = crate::from_bytes(&[0x12, 0x34, 0x56, 0x78]);
140 assert_eq!(result.err().unwrap(), Error::DeserializeUnexpectedEnd);
141 }
142}