1use serde::{Deserializer, Serializer};
9use std::marker::PhantomData;
10use zerocopy::{FromBytes, Immutable, IntoBytes};
11
12static_assertions::assert_cfg!(target_endian = "little");
14pub trait SerializeAsBytes {
17 type Inner: FromBytes + Immutable + Copy;
18
19 fn as_bytes(&self) -> &[u8];
21
22 fn from_vec(slice: Vec<Self::Inner>) -> Self;
24}
25
26impl<T: FromBytes + IntoBytes + Immutable + Copy> SerializeAsBytes for Vec<T> {
27 type Inner = T;
28
29 fn as_bytes(&self) -> &[u8] {
30 self.as_slice().as_bytes()
31 }
32
33 fn from_vec(slice: Vec<T>) -> Self {
34 slice
35 }
36}
37
38impl<T: FromBytes + IntoBytes + Immutable + Copy> SerializeAsBytes for Box<[T]> {
39 type Inner = T;
40
41 fn as_bytes(&self) -> &[u8] {
42 (&**self).as_bytes()
43 }
44
45 fn from_vec(slice: Vec<T>) -> Self {
46 slice.into_boxed_slice()
47 }
48}
49
50pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
52where
53 T: SerializeAsBytes,
54 S: Serializer,
55{
56 serializer.serialize_bytes(value.as_bytes())
57}
58
59pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
61where
62 T: SerializeAsBytes,
63 D: Deserializer<'de>,
64{
65 debug_assert!(size_of::<T::Inner>() > 0);
67
68 if align_of::<T::Inner>() == align_of::<u8>() {
71 deserializer.deserialize_byte_buf(Visitor(PhantomData::<T>))
73 } else {
74 deserializer.deserialize_bytes(Visitor(PhantomData::<T>))
76 }
77}
78
79struct Visitor<T>(PhantomData<T>);
81impl<'de, T> serde::de::Visitor<'de> for Visitor<T>
82where
83 T: SerializeAsBytes,
84{
85 type Value = T;
86
87 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 write!(
89 formatter,
90 "a byte array with a length that is a multiple of {}",
91 size_of::<T::Inner>()
92 )
93 }
94
95 fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
96 where
97 E: serde::de::Error,
98 {
99 if !bytes.len().is_multiple_of(size_of::<T::Inner>()) {
100 return Err(E::custom(
101 "input bytes are not a multiple of the size of the desired type",
102 ));
103 }
104 let elements = bytes.len() / size_of::<T::Inner>();
105 let mut vec: Vec<T::Inner> = Vec::with_capacity(elements);
106 let dst = vec.spare_capacity_mut();
107 unsafe {
108 std::ptr::copy_nonoverlapping(
115 bytes.as_ptr(),
116 dst.as_mut_ptr().cast::<u8>(),
117 bytes.len(),
118 );
119 vec.set_len(elements);
121 }
122 Ok(T::from_vec(vec))
123 }
124
125 fn visit_byte_buf<E>(self, bytes: Vec<u8>) -> Result<Self::Value, E>
126 where
127 E: serde::de::Error,
128 {
129 debug_assert!(align_of::<T::Inner>() == align_of::<u8>());
132 debug_assert!(size_of::<T::Inner>() > 0);
134
135 if !bytes.len().is_multiple_of(size_of::<T::Inner>()) {
136 return Err(E::custom(
137 "input bytes are not a multiple of the size of the desired type",
138 ));
139 }
140 let elements = bytes.len() / size_of::<T::Inner>();
141
142 let vec = if !bytes.capacity().is_multiple_of(size_of::<T::Inner>()) {
145 let ptr = Box::into_raw(bytes.into_boxed_slice());
149 unsafe { Vec::from_raw_parts(ptr.cast::<T::Inner>(), elements, elements) }
158 } else {
159 let (ptr, _size, capacity) = bytes.into_raw_parts();
160 let capacity = capacity / size_of::<T::Inner>();
161 unsafe { Vec::from_raw_parts(ptr.cast::<T::Inner>(), elements, capacity) }
169 };
170 Ok(T::from_vec(vec))
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use crate::serialized_types::{LATEST_VERSION, Versioned};
177 use serde::{Deserialize, Serialize};
178
179 #[fuchsia::test]
180 fn test_boxed_slice_of_u8_is_the_same() {
181 #[derive(Serialize, Deserialize, Versioned)]
182 struct Regular(Box<[u8]>);
183 #[derive(Serialize, Deserialize, Versioned, PartialEq, Eq, Debug)]
184 struct Optimized(#[serde(with = "crate::zerocopy_serialization")] Box<[u8]>);
185
186 let regular = Regular(vec![0, 1, 2, 3, 254, 255].into_boxed_slice());
187 let mut regular_serialized = Vec::new();
188 regular.serialize_into(&mut regular_serialized).unwrap();
189
190 let optimized = Optimized(regular.0);
191 let mut optimized_serialized = Vec::new();
192 optimized.serialize_into(&mut optimized_serialized).unwrap();
193
194 assert_eq!(regular_serialized, optimized_serialized);
195
196 assert_eq!(
197 Optimized::deserialize_from(&mut optimized_serialized.as_slice(), LATEST_VERSION)
198 .unwrap(),
199 optimized
200 );
201 }
202
203 #[fuchsia::test]
204 fn test_vec_of_u8_is_the_same() {
205 #[derive(Serialize, Deserialize, Versioned)]
206 struct Regular(Vec<u8>);
207 #[derive(Serialize, Deserialize, Versioned, PartialEq, Eq, Debug)]
208 struct Optimized(#[serde(with = "crate::zerocopy_serialization")] Vec<u8>);
209
210 let regular = Regular(vec![0, 1, 2, 3, 254, 255]);
211 let mut regular_serialized = Vec::new();
212 regular.serialize_into(&mut regular_serialized).unwrap();
213
214 let optimized = Optimized(regular.0);
215 let mut optimized_serialized = Vec::new();
216 optimized.serialize_into(&mut optimized_serialized).unwrap();
217
218 assert_eq!(regular_serialized, optimized_serialized);
219
220 assert_eq!(
221 Optimized::deserialize_from(&mut optimized_serialized.as_slice(), LATEST_VERSION)
222 .unwrap(),
223 optimized
224 );
225 }
226
227 #[fuchsia::test]
228 fn test_boxed_slice_of_array_of_u8() {
229 #[derive(Serialize, Deserialize, Versioned)]
230 struct Regular(Box<[[u8; 4]]>);
231 #[derive(Serialize, Deserialize, Versioned, PartialEq, Eq, Debug)]
232 struct Optimized(#[serde(with = "crate::zerocopy_serialization")] Box<[[u8; 4]]>);
233
234 let regular = Regular(vec![[0, 1, 2, 3], [252, 253, 254, 255]].into_boxed_slice());
235 let mut regular_serialized = Vec::new();
236 regular.serialize_into(&mut regular_serialized).unwrap();
237
238 let optimized = Optimized(regular.0);
239 let mut optimized_serialized = Vec::new();
240 optimized.serialize_into(&mut optimized_serialized).unwrap();
241
242 assert_eq!(®ular_serialized[1..], &optimized_serialized[1..]);
244 assert_eq!(regular_serialized[0], 2);
245 assert_eq!(optimized_serialized[0], 8);
246
247 assert_eq!(
248 Optimized::deserialize_from(&mut optimized_serialized.as_slice(), LATEST_VERSION)
249 .unwrap(),
250 optimized
251 );
252 }
253
254 #[fuchsia::test]
255 fn test_vec_of_array_of_u8() {
256 #[derive(Serialize, Deserialize, Versioned)]
257 struct Regular(Vec<[u8; 4]>);
258 #[derive(Serialize, Deserialize, Versioned, PartialEq, Eq, Debug)]
259 struct Optimized(#[serde(with = "crate::zerocopy_serialization")] Vec<[u8; 4]>);
260
261 let regular = Regular(vec![[0, 1, 2, 3], [252, 253, 254, 255]]);
262 let mut regular_serialized = Vec::new();
263 regular.serialize_into(&mut regular_serialized).unwrap();
264
265 let optimized = Optimized(regular.0);
266 let mut optimized_serialized = Vec::new();
267 optimized.serialize_into(&mut optimized_serialized).unwrap();
268
269 assert_eq!(®ular_serialized[1..], &optimized_serialized[1..]);
271 assert_eq!(regular_serialized[0], 2);
272 assert_eq!(optimized_serialized[0], 8);
273
274 assert_eq!(
275 Optimized::deserialize_from(&mut optimized_serialized.as_slice(), LATEST_VERSION)
276 .unwrap(),
277 optimized
278 );
279 }
280
281 #[fuchsia::test]
282 fn test_vec_of_u64_round_trip() {
283 #[derive(Serialize, Deserialize, Versioned, PartialEq, Eq, Debug)]
284 struct Optimized(#[serde(with = "crate::zerocopy_serialization")] Vec<u64>);
285
286 let optimized =
287 Optimized(vec![0, 1, u32::MAX as u64, u32::MAX as u64 + 1, u64::MAX - 1, u64::MAX]);
288 let mut optimized_serialized = Vec::new();
289 optimized.serialize_into(&mut optimized_serialized).unwrap();
290
291 assert_eq!(optimized_serialized.len(), 1 + 6 * 8);
293
294 assert_eq!(
295 Optimized::deserialize_from(&mut optimized_serialized.as_slice(), LATEST_VERSION)
296 .unwrap(),
297 optimized
298 );
299 }
300
301 #[fuchsia::test]
302 fn test_empty_vec() {
303 #[derive(Serialize, Deserialize, Versioned, PartialEq, Eq, Debug)]
304 struct OptimizedVec(#[serde(with = "crate::zerocopy_serialization")] Vec<u8>);
305 let optimized = OptimizedVec(Vec::new());
306 let mut buf = Vec::new();
307 optimized.serialize_into(&mut buf).unwrap();
308 assert_eq!(
309 OptimizedVec::deserialize_from(&mut buf.as_slice(), LATEST_VERSION).unwrap(),
310 optimized
311 );
312 }
313
314 #[fuchsia::test]
315 fn test_visit_byte_buf_capacity_mismatch() {
316 let mut bytes = Vec::with_capacity(11);
318 bytes.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8]);
319 assert_eq!(bytes.len(), 8);
320 assert!(bytes.capacity() >= 11);
321 assert!(!bytes.capacity().is_multiple_of(size_of::<u32>()));
322
323 let visitor = super::Visitor(std::marker::PhantomData::<Vec<[u8; 4]>>);
325 let result: Vec<[u8; 4]> =
326 serde::de::Visitor::visit_byte_buf::<serde::de::value::Error>(visitor, bytes)
327 .expect("visit_byte_buf failed");
328 assert_eq!(&result, &[[1, 2, 3, 4], [5, 6, 7, 8]]);
329 }
330
331 #[fuchsia::test]
332 fn test_visit_byte_buf_invalid_length() {
333 let bytes = vec![1, 2, 3, 4, 5]; let visitor = super::Visitor(std::marker::PhantomData::<Vec<[u8; 4]>>);
335 let result: Result<_, serde::de::value::Error> =
336 serde::de::Visitor::visit_byte_buf(visitor, bytes);
337 assert!(result.is_err());
338 }
339
340 #[fuchsia::test]
341 fn test_visit_bytes_invalid_length() {
342 let bytes = vec![1, 2, 3, 4, 5]; let visitor = super::Visitor(std::marker::PhantomData::<Vec<u16>>);
344 let result: Result<_, serde::de::value::Error> =
345 serde::de::Visitor::visit_bytes(visitor, &bytes);
346 assert!(result.is_err());
347 }
348
349 #[fuchsia::test]
350 fn test_visit_bytes_with_bad_alignment() {
351 const E1: u64 = 0x0123456789ABCDEF;
352 const E2: u64 = u64::MAX;
353 let mut bytes: Vec<u8> = vec![0, 1, 2];
356 bytes.extend_from_slice(&E1.to_le_bytes());
357 bytes.extend_from_slice(&E2.to_le_bytes());
358 assert!(!(&bytes[3..]).as_ptr().cast::<u64>().is_aligned());
359 let visitor = super::Visitor(std::marker::PhantomData::<Vec<u64>>);
360 let result: Vec<u64> =
361 serde::de::Visitor::visit_bytes::<serde::de::value::Error>(visitor, &bytes[3..])
362 .expect("visit_bytes failed");
363 assert_eq!(&result, &[E1, E2]);
364 }
365
366 #[fuchsia::test]
367 fn test_visit_bytes_with_empty_slice() {
368 let visitor = super::Visitor(std::marker::PhantomData::<Vec<u64>>);
369 let result: Vec<u64> =
370 serde::de::Visitor::visit_bytes::<serde::de::value::Error>(visitor, &[])
371 .expect("visit_bytes failed");
372 assert!(result.is_empty());
373 }
374}