chf/
serde_macros.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Macros for serde trait implementations, and supporting code.
4//!
5
6/// Functions used by serde impls of all hashes.
7#[cfg(feature = "serde")]
8pub mod serde_details {
9    use core::marker::PhantomData;
10    use core::str::FromStr;
11    use core::{fmt, ops, str};
12
13    use crate::FromSliceError;
14    struct HexVisitor<ValueT>(PhantomData<ValueT>);
15    use serde::{de, Deserializer, Serializer};
16
17    impl<'de, ValueT> de::Visitor<'de> for HexVisitor<ValueT>
18    where
19        ValueT: FromStr,
20        <ValueT as FromStr>::Err: fmt::Display,
21    {
22        type Value = ValueT;
23
24        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
25            formatter.write_str("an ASCII hex string")
26        }
27
28        fn visit_bytes<E>(self, v: &[u8]) -> core::result::Result<Self::Value, E>
29        where
30            E: de::Error,
31        {
32            if let Ok(hex) = str::from_utf8(v) {
33                Self::Value::from_str(hex).map_err(E::custom)
34            } else {
35                return Err(E::invalid_value(de::Unexpected::Bytes(v), &self));
36            }
37        }
38
39        fn visit_str<E>(self, v: &str) -> core::result::Result<Self::Value, E>
40        where
41            E: de::Error,
42        {
43            Self::Value::from_str(v).map_err(E::custom)
44        }
45    }
46
47    struct BytesVisitor<ValueT>(PhantomData<ValueT>);
48
49    impl<'de, ValueT> de::Visitor<'de> for BytesVisitor<ValueT>
50    where
51        ValueT: SerdeHash,
52        <ValueT as FromStr>::Err: fmt::Display,
53    {
54        type Value = ValueT;
55
56        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
57            formatter.write_str("a bytestring")
58        }
59
60        fn visit_bytes<E>(self, v: &[u8]) -> core::result::Result<Self::Value, E>
61        where
62            E: de::Error,
63        {
64            SerdeHash::from_slice_delegated(v).map_err(|_| {
65                // from_slice only errors on incorrect length
66                E::invalid_length(v.len(), &stringify!(N))
67            })
68        }
69    }
70
71    /// Default serialization/deserialization methods.
72    pub trait SerdeHash
73    where
74        Self: Sized
75            + FromStr
76            + fmt::Display
77            + ops::Index<usize, Output = u8>
78            + ops::Index<ops::RangeFull, Output = [u8]>,
79        <Self as FromStr>::Err: fmt::Display,
80    {
81        /// Size, in bits, of the hash.
82        const N: usize;
83
84        /// Helper function to turn a deserialized slice into the correct hash type.
85        fn from_slice_delegated(sl: &[u8]) -> core::result::Result<Self, FromSliceError>;
86
87        /// Do serde serialization.
88        fn serialize<S: Serializer>(&self, s: S) -> core::result::Result<S::Ok, S::Error> {
89            if s.is_human_readable() {
90                s.collect_str(self)
91            } else {
92                s.serialize_bytes(&self[..])
93            }
94        }
95
96        /// Do serde deserialization.
97        fn deserialize<'de, D: Deserializer<'de>>(d: D) -> core::result::Result<Self, D::Error> {
98            if d.is_human_readable() {
99                d.deserialize_str(HexVisitor::<Self>(PhantomData))
100            } else {
101                d.deserialize_bytes(BytesVisitor::<Self>(PhantomData))
102            }
103        }
104    }
105}
106
107/// Implements `Serialize` and `Deserialize` for a type `$t` which
108/// represents a newtype over a byte-slice over length `$len`.
109#[macro_export]
110#[cfg(feature = "serde")]
111macro_rules! serde_impl(
112    ($t:ident, $len:expr $(, $gen:ident: $gent:ident)*) => (
113        impl<$($gen: $gent),*> $crate::serde_macros::serde_details::SerdeHash for $t<$($gen),*> {
114            const N : usize = $len;
115            fn from_slice_delegated(sl: &[u8]) -> core::result::Result<Self, $crate::FromSliceError> {
116                $t::from_slice(sl)
117            }
118        }
119
120        impl<$($gen: $gent),*> $crate::serde::Serialize for $t<$($gen),*> {
121            fn serialize<S: $crate::serde::Serializer>(&self, s: S) -> core::result::Result<S::Ok, S::Error> {
122                $crate::serde_macros::serde_details::SerdeHash::serialize(self, s)
123            }
124        }
125
126        impl<'de $(, $gen: $gent)*> $crate::serde::Deserialize<'de> for $t<$($gen),*> {
127            fn deserialize<D: $crate::serde::Deserializer<'de>>(d: D) -> core::result::Result<$t<$($gen),*>, D::Error> {
128                $crate::serde_macros::serde_details::SerdeHash::deserialize(d)
129            }
130        }
131));
132
133/// Does an "empty" serde implementation for the configuration without serde feature.
134#[macro_export]
135#[cfg(not(feature = "serde"))]
136macro_rules! serde_impl(
137        ($t:ident, $len:expr $(, $gen:ident: $gent:ident)*) => ()
138);