Skip to main content

blob_metadata/
zerocopy_serialization.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Efficient serialization and deserialization for `Vec<T>` and `Box<[T]>` where `T` supports
6//! zerocopy.
7
8use fprint::TypeFingerprint;
9use serde::{Deserializer, Serializer};
10use std::marker::PhantomData;
11use zerocopy::{FromBytes, Immutable, IntoBytes};
12
13// Only little endian is supported.
14static_assertions::assert_cfg!(target_endian = "little");
15
16pub trait SerializeAsBytes {
17    type Inner: FromBytes + Immutable + Copy;
18
19    fn as_bytes(&self) -> &[u8];
20    fn from_vec(slice: Vec<Self::Inner>) -> Self;
21}
22
23impl<T: FromBytes + IntoBytes + Immutable + Copy> SerializeAsBytes for Vec<T> {
24    type Inner = T;
25
26    fn as_bytes(&self) -> &[u8] {
27        self.as_slice().as_bytes()
28    }
29
30    fn from_vec(slice: Vec<T>) -> Self {
31        slice
32    }
33}
34
35impl<T: FromBytes + IntoBytes + Immutable + Copy> SerializeAsBytes for Box<[T]> {
36    type Inner = T;
37
38    fn as_bytes(&self) -> &[u8] {
39        (&**self).as_bytes()
40    }
41
42    fn from_vec(slice: Vec<T>) -> Self {
43        slice.into_boxed_slice()
44    }
45}
46
47pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
48where
49    T: SerializeAsBytes,
50    S: Serializer,
51{
52    serializer.serialize_bytes(value.as_bytes())
53}
54
55pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
56where
57    T: SerializeAsBytes,
58    D: Deserializer<'de>,
59{
60    struct Visitor<T: SerializeAsBytes>(PhantomData<T>);
61
62    impl<'de, T: SerializeAsBytes> serde::de::Visitor<'de> for Visitor<T> {
63        type Value = T;
64
65        fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66            formatter.write_str("a byte slice")
67        }
68
69        fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
70        where
71            E: serde::de::Error,
72        {
73            if v.len() % std::mem::size_of::<T::Inner>() != 0 {
74                return Err(E::custom("Invalid byte slice length for zerocopy type"));
75            }
76            let slice = unsafe {
77                std::slice::from_raw_parts(
78                    v.as_ptr().cast::<T::Inner>(),
79                    v.len() / std::mem::size_of::<T::Inner>(),
80                )
81            };
82            Ok(T::from_vec(slice.to_vec()))
83        }
84    }
85
86    deserializer.deserialize_bytes(Visitor(PhantomData))
87}
88
89pub fn fingerprint<T: SerializeAsBytes + TypeFingerprint>() -> String {
90    format!("AsBytes<{}>", T::fingerprint())
91}