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