1use {
4 super::Multihash,
5 core::{fmt, mem, slice},
6 serde::{
7 de::{self, SeqAccess, Visitor},
8 ser,
9 Deserialize,
10 Deserializer,
11 Serialize,
12 Serializer,
13 },
14};
15
16const MAXIMUM_PREFIX_SIZE: usize = 11;
20
21#[repr(C, packed)]
28struct Buffer<const SIZE_FIRST: usize, const SIZE_SECOND: usize> {
29 first: [u8; SIZE_FIRST],
30 second: [u8; SIZE_SECOND],
31}
32
33#[allow(unsafe_code)]
34impl<const SIZE_FIRST: usize, const SIZE_SECOND: usize>
35 Buffer<SIZE_FIRST, SIZE_SECOND>
36{
37 fn new() -> Self {
38 Self {
39 first: [0; SIZE_FIRST],
40 second: [0; SIZE_SECOND],
41 }
42 }
43
44 fn as_slice(&self) -> &[u8] {
45 unsafe {
46 slice::from_raw_parts(self as *const _ as _, mem::size_of::<Self>())
47 }
48 }
49
50 fn as_mut_slice(&mut self) -> &mut [u8] {
51 unsafe {
52 slice::from_raw_parts_mut(self as *mut _ as _, mem::size_of::<Self>())
53 }
54 }
55}
56
57impl<const SIZE: usize> Serialize for Multihash<SIZE> {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: Serializer,
61 {
62 let mut buffer = Buffer::<MAXIMUM_PREFIX_SIZE, SIZE>::new();
63 let bytes_written = self
64 .write(buffer.as_mut_slice())
65 .map_err(|_| ser::Error::custom("Failed to serialize Multihash"))?;
66 serializer.serialize_bytes(&buffer.as_slice()[..bytes_written])
67 }
68}
69
70struct BytesVisitor<const SIZE: usize>;
71
72impl<'de, const SIZE: usize> Visitor<'de> for BytesVisitor<SIZE> {
73 type Value = Multihash<SIZE>;
74
75 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
76 write!(fmt, "a valid Multihash in bytes")
77 }
78
79 fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
80 where
81 E: de::Error,
82 {
83 Multihash::<SIZE>::from_bytes(bytes)
84 .map_err(|_| de::Error::custom("Failed to deserialize Multihash"))
85 }
86
87 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
90 where
91 A: SeqAccess<'de>,
92 {
93 let mut buffer = Buffer::<MAXIMUM_PREFIX_SIZE, SIZE>::new();
94 let bytes = buffer.as_mut_slice();
95
96 let mut pos = 0;
98 while let Some(byte) = seq.next_element()? {
99 bytes[pos] = byte;
100 pos += 1;
101 if pos >= bytes.len() {
102 return Err(de::Error::custom("Failed to deserialize Multihash"));
103 }
104 }
105
106 Multihash::<SIZE>::from_bytes(&bytes[..pos])
107 .map_err(|_| de::Error::custom("Failed to deserialize Multihash"))
108 }
109}
110
111impl<'de, const SIZE: usize> Deserialize<'de> for Multihash<SIZE> {
112 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
113 where
114 D: Deserializer<'de>,
115 {
116 deserializer.deserialize_bytes(BytesVisitor)
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use {
123 super::*,
124 alloc::format,
125 core::ptr,
126 serde_test::{assert_tokens, Token},
127 };
128
129 const SHA2_256_CODE: u64 = 0x12;
130 const DIGEST: [u8; 32] = [
131 159, 228, 204, 198, 222, 22, 114, 79, 58, 48, 199, 232, 242, 84, 243, 198,
132 71, 25, 134, 172, 177, 248, 216, 207, 142, 150, 206, 42, 215, 219, 231,
133 251,
134 ];
135
136 #[test]
137 fn test_serde_json() {
138 let expected_json = format!(
140 "[{},{},159,228,204,198,222,22,114,79,58,48,199,232,242,84,243,198,71,\
141 25,134,172,177,248,216,207,142,150,206,42,215,219,231,251]",
142 SHA2_256_CODE as u8,
143 DIGEST.len() as u8
144 );
145
146 let mh = Multihash::<32>::wrap(SHA2_256_CODE, &DIGEST).unwrap();
147
148 let json = serde_json::to_string(&mh).unwrap();
149 assert_eq!(json, expected_json);
150
151 let mh_decoded: Multihash<32> = serde_json::from_str(&json).unwrap();
152 assert_eq!(mh, mh_decoded);
153 }
154
155 #[test]
156 fn test_serde_test() {
157 const ENCODED_MULTIHASH_BYTES: [u8; 34] = [
159 SHA2_256_CODE as u8,
160 DIGEST.len() as u8,
161 159,
162 228,
163 204,
164 198,
165 222,
166 22,
167 114,
168 79,
169 58,
170 48,
171 199,
172 232,
173 242,
174 84,
175 243,
176 198,
177 71,
178 25,
179 134,
180 172,
181 177,
182 248,
183 216,
184 207,
185 142,
186 150,
187 206,
188 42,
189 215,
190 219,
191 231,
192 251,
193 ];
194
195 let mh = Multihash::<32>::wrap(SHA2_256_CODE, &DIGEST).unwrap();
196
197 assert_tokens(&mh, &[Token::Bytes(&ENCODED_MULTIHASH_BYTES)]);
199
200 serde_test::assert_de_tokens(&mh, &[
202 Token::Seq { len: Some(34) },
203 Token::U8(SHA2_256_CODE as u8),
204 Token::U8(DIGEST.len() as u8),
205 Token::U8(159),
206 Token::U8(228),
207 Token::U8(204),
208 Token::U8(198),
209 Token::U8(222),
210 Token::U8(22),
211 Token::U8(114),
212 Token::U8(79),
213 Token::U8(58),
214 Token::U8(48),
215 Token::U8(199),
216 Token::U8(232),
217 Token::U8(242),
218 Token::U8(84),
219 Token::U8(243),
220 Token::U8(198),
221 Token::U8(71),
222 Token::U8(25),
223 Token::U8(134),
224 Token::U8(172),
225 Token::U8(177),
226 Token::U8(248),
227 Token::U8(216),
228 Token::U8(207),
229 Token::U8(142),
230 Token::U8(150),
231 Token::U8(206),
232 Token::U8(42),
233 Token::U8(215),
234 Token::U8(219),
235 Token::U8(231),
236 Token::U8(251),
237 Token::SeqEnd,
238 ]);
239 }
240
241 #[test]
242 fn test_buffer_alignment() {
243 const SIZE_FIRST: usize = 11;
244 const SIZE_SECOND: usize = 13;
245 let buffer = Buffer::<SIZE_FIRST, SIZE_SECOND>::new();
246
247 let start_first = ptr::addr_of!(buffer.first) as *const u8;
250 let start_second = ptr::addr_of!(buffer.second) as *const u8;
251 #[allow(unsafe_code)]
252 unsafe {
253 assert_eq!(start_second.offset_from(start_first), SIZE_FIRST as isize);
254 };
255 }
256
257 #[test]
258 fn test_buffer() {
259 const SIZE_FIRST: usize = 3;
260 const SIZE_SECOND: usize = 8;
261 let mut buffer = Buffer::<SIZE_FIRST, SIZE_SECOND>::new();
262
263 let data: [u8; SIZE_FIRST + SIZE_SECOND] =
264 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
265 buffer.as_mut_slice().copy_from_slice(&data);
266 assert_eq!(buffer.as_slice(), data);
267 }
268}