Skip to main content

serde_multipart/
codec.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8
9use serde::Deserialize;
10use serde::Serialize;
11use serde::de::DeserializeOwned;
12use typeuri::Named;
13
14use crate::Part;
15use crate::part::BincodeDeserializer;
16use crate::part::BincodeSerializer;
17
18/// Converts a framework type to and from a typed multipart part.
19pub trait PartCodec: Sized
20where
21    Self::Repr: Serialize + DeserializeOwned + Named,
22    for<'a> Self::Repr: std::convert::TryFrom<&'a Self, Error = crate::Error>,
23    Self: std::convert::TryFrom<Self::Repr, Error = crate::Error>,
24{
25    /// The bincode representation stored in typed parts.
26    type Repr;
27
28    /// Convert this value to its typed part representation.
29    fn to_repr(&self) -> crate::Result<Self::Repr> {
30        Self::Repr::try_from(self)
31    }
32
33    /// Rebuild this value from its typed part representation.
34    fn from_repr(repr: Self::Repr) -> crate::Result<Self> {
35        Self::try_from(repr)
36    }
37
38    /// Convert this value to a typed part.
39    fn to_part(&self) -> crate::Result<Part> {
40        Part::serialize(&self.to_repr()?)
41    }
42
43    /// Rebuild this value from a typed part.
44    fn from_part(part: Part) -> crate::Result<Self> {
45        let repr = part.deserialized::<Self::Repr>()?;
46        Self::from_repr(repr)
47    }
48}
49
50/// Serialize a value that implements [`PartCodec`].
51pub fn serialize_part_codec<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
52where
53    T: PartCodec,
54    S: serde::Serializer,
55{
56    <T as PartCodecSerializer<S>>::serialize(value, serializer)
57}
58
59/// Deserialize a value that implements [`PartCodec`].
60pub fn deserialize_part_codec<'de, T, D>(deserializer: D) -> Result<T, D::Error>
61where
62    T: PartCodec,
63    D: serde::Deserializer<'de>,
64{
65    <T as PartCodecDeserializer<'de, D>>::deserialize(deserializer)
66}
67
68trait PartCodecSerializer<S: serde::Serializer> {
69    fn serialize(this: &Self, serializer: S) -> Result<S::Ok, S::Error>;
70}
71
72impl<T, S> PartCodecSerializer<S> for T
73where
74    T: PartCodec,
75    S: serde::Serializer,
76{
77    default fn serialize(this: &Self, serializer: S) -> Result<S::Ok, S::Error> {
78        this.to_repr()
79            .map_err(serde::ser::Error::custom)?
80            .serialize(serializer)
81    }
82}
83
84impl<'a, T> PartCodecSerializer<&'a mut BincodeSerializer> for T
85where
86    T: PartCodec,
87{
88    fn serialize(this: &Self, serializer: &'a mut BincodeSerializer) -> Result<(), bincode::Error> {
89        let part = this
90            .to_part()
91            .map_err(<bincode::Error as serde::ser::Error>::custom)?;
92        serializer.serialize_part(&part);
93        Ok(())
94    }
95}
96
97trait PartCodecDeserializer<'de, D: serde::Deserializer<'de>>: Sized {
98    fn deserialize(deserializer: D) -> Result<Self, D::Error>;
99}
100
101impl<'de, T, D> PartCodecDeserializer<'de, D> for T
102where
103    T: PartCodec,
104    D: serde::Deserializer<'de>,
105{
106    default fn deserialize(deserializer: D) -> Result<Self, D::Error> {
107        let repr = T::Repr::deserialize(deserializer)?;
108        T::from_repr(repr).map_err(serde::de::Error::custom)
109    }
110}
111
112impl<'a, T> PartCodecDeserializer<'_, &'a mut BincodeDeserializer> for T
113where
114    T: PartCodec,
115{
116    fn deserialize(deserializer: &'a mut BincodeDeserializer) -> Result<Self, bincode::Error> {
117        let part = deserializer.deserialize_part()?;
118        T::from_part(part).map_err(<bincode::Error as serde::de::Error>::custom)
119    }
120}
121
122/// Implement [`PartCodec`], [`serde::Serialize`], and [`serde::Deserialize`].
123#[macro_export]
124macro_rules! part_codec {
125    (
126        impl <$($impl_generics:ident),+> $ty:ty
127        {
128            type Repr = $repr:ty;
129        }
130    ) => {
131        $crate::part_codec! {
132            @expand
133            [<$($impl_generics),+>]
134            [<'de, $($impl_generics),+>]
135            [$ty]
136            [$repr]
137        }
138    };
139
140    (
141        impl $ty:ty
142        {
143            type Repr = $repr:ty;
144        }
145    ) => {
146        $crate::part_codec! {
147            @expand
148            []
149            [<'de>]
150            [$ty]
151            [$repr]
152        }
153    };
154
155    (
156        @expand
157        [$($impl_generics:tt)*]
158        [$($de_impl_generics:tt)*]
159        [$ty:ty]
160        [$repr:ty]
161    ) => {
162        impl $($impl_generics)* $crate::PartCodec for $ty
163        where
164            $repr: serde::Serialize + serde::de::DeserializeOwned + typeuri::Named,
165            for<'a> $repr: std::convert::TryFrom<&'a $ty, Error = $crate::Error>,
166            $ty: std::convert::TryFrom<$repr, Error = $crate::Error>,
167        {
168            type Repr = $repr;
169        }
170
171        impl $($impl_generics)* serde::Serialize for $ty
172        where
173            $ty: $crate::PartCodec,
174        {
175            fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
176            where
177                S: serde::Serializer,
178            {
179                $crate::serialize_part_codec(self, serializer)
180            }
181        }
182
183        impl $($de_impl_generics)* serde::Deserialize<'de> for $ty
184        where
185            $ty: $crate::PartCodec,
186        {
187            fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
188            where
189                D: serde::Deserializer<'de>,
190            {
191                $crate::deserialize_part_codec(deserializer)
192            }
193        }
194    };
195}