vitaminc_protected/exportable/
safe_serialize.rs

1use std::num::{
2    NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
3    NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
4};
5
6use crate::Controlled;
7use serde::ser::SerializeTuple;
8use serde::{Serialize, Serializer};
9
10// TODO: Create a serialize method on exportable which maps into the serialized form
11// Exportable should also implement a "safe" version of Hex (serdect)
12// And a reader?
13
14// TODO: SafeSerialize *maybe* should consume self
15pub trait SafeSerialize {
16    fn safe_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
17    where
18        S: Serializer;
19}
20
21/// Blanket implementation for all controlled types who's inner type implements `SafeSerialize`.
22impl<T> SafeSerialize for T
23where
24    T::Inner: SafeSerialize,
25    T: Controlled,
26{
27    fn safe_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
28    where
29        S: Serializer,
30    {
31        self.risky_ref().safe_serialize(serializer)
32    }
33}
34
35// This code is adapted from the serde source code
36macro_rules! impl_safe_serialize {
37    ($type:ty, $serialize_fn:ident $($cast:tt)*) => {
38        impl SafeSerialize for $type {
39            #[inline]
40            fn safe_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
41            where
42                S: Serializer,
43            {
44                serializer.$serialize_fn(*self $($cast)*)
45            }
46        }
47    };
48}
49
50impl_safe_serialize!(u8, serialize_u8);
51impl_safe_serialize!(u16, serialize_u16);
52impl_safe_serialize!(u32, serialize_u32);
53impl_safe_serialize!(u64, serialize_u64);
54impl_safe_serialize!(u128, serialize_u128);
55impl_safe_serialize!(usize, serialize_u64 as u64);
56impl_safe_serialize!(i8, serialize_i8);
57impl_safe_serialize!(i16, serialize_i16);
58impl_safe_serialize!(i32, serialize_i32);
59impl_safe_serialize!(i64, serialize_i64);
60impl_safe_serialize!(i128, serialize_i128);
61impl_safe_serialize!(isize, serialize_i64 as i64);
62impl_safe_serialize!(f32, serialize_f32);
63impl_safe_serialize!(f64, serialize_f64);
64impl_safe_serialize!(char, serialize_char);
65impl_safe_serialize!(bool, serialize_bool);
66
67impl SafeSerialize for String {
68    #[inline]
69    fn safe_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70    where
71        S: Serializer,
72    {
73        serializer.serialize_str(self)
74    }
75}
76
77impl<const N: usize> SafeSerialize for [u8; N] {
78    fn safe_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
79    where
80        S: Serializer,
81    {
82        serializer.serialize_bytes(self)
83    }
84}
85
86macro_rules! impl_safe_serialize_nonzero {
87    ($type:ty, $serialize_fn:ident $($cast:tt)*) => {
88        impl SafeSerialize for $type {
89            #[inline]
90            fn safe_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91            where
92                S: Serializer,
93            {
94                serializer.$serialize_fn(self.get() $($cast)*)
95            }
96        }
97    };
98}
99
100impl_safe_serialize_nonzero!(NonZeroU8, serialize_u8);
101impl_safe_serialize_nonzero!(NonZeroU16, serialize_u16);
102impl_safe_serialize_nonzero!(NonZeroU32, serialize_u32);
103impl_safe_serialize_nonzero!(NonZeroU64, serialize_u64);
104impl_safe_serialize_nonzero!(NonZeroU128, serialize_u128);
105impl_safe_serialize_nonzero!(NonZeroUsize, serialize_u64 as u64);
106impl_safe_serialize_nonzero!(NonZeroI8, serialize_i8);
107impl_safe_serialize_nonzero!(NonZeroI16, serialize_i16);
108impl_safe_serialize_nonzero!(NonZeroI32, serialize_i32);
109impl_safe_serialize_nonzero!(NonZeroI64, serialize_i64);
110impl_safe_serialize_nonzero!(NonZeroI128, serialize_i128);
111impl_safe_serialize_nonzero!(NonZeroIsize, serialize_i64 as i64);
112
113macro_rules! tuple_impls {
114    ($($len:expr => ($($n:tt $name:ident)+))+) => {
115        $(
116            #[cfg_attr(docsrs, doc(hidden))]
117            impl<$($name),+> SafeSerialize for ($($name,)+)
118            where
119                $($name: SafeSerialize + Serialize,)+
120            {
121                tuple_impl_body!($len => ($($n)+));
122            }
123        )+
124    };
125}
126
127macro_rules! tuple_impl_body {
128    ($len:expr => ($($n:tt)+)) => {
129        #[inline]
130        fn safe_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
131        where
132            S: Serializer,
133        {
134            let mut tuple = serializer.serialize_tuple($len)?;
135            $(
136                tuple.serialize_element(&self.$n)?;
137            )+
138            tuple.end()
139        }
140    };
141}
142/// This trait is implemented for tuples up to 10 items long (the same as Zeroize).
143impl<T> SafeSerialize for (T,)
144where
145    T: Serialize + SafeSerialize,
146{
147    tuple_impl_body!(1 => (0));
148}
149
150tuple_impls! {
151    2 => (0 T0 1 T1)
152    3 => (0 T0 1 T1 2 T2)
153    4 => (0 T0 1 T1 2 T2 3 T3)
154    5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
155    6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
156    7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
157    8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
158    9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
159    10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
160}