ethdigest/
serde.rs

1//! Serde serialization implementation for Ethereum 32-byte digests.
2
3use crate::Digest;
4use core::fmt::{self, Formatter};
5use serde::{
6    de::{self, Deserializer, Visitor},
7    ser::Serializer,
8    Deserialize, Serialize,
9};
10
11impl<'de> Deserialize<'de> for Digest {
12    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
13    where
14        D: Deserializer<'de>,
15    {
16        deserializer.deserialize_str(DigestVisitor)
17    }
18}
19
20struct DigestVisitor;
21
22impl<'de> Visitor<'de> for DigestVisitor {
23    type Value = Digest;
24
25    fn expecting(&self, f: &mut Formatter) -> fmt::Result {
26        f.write_str("a `0x`-prefixed 20-byte hex string")
27    }
28
29    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
30    where
31        E: de::Error,
32    {
33        s.strip_prefix("0x")
34            .ok_or_else(|| de::Error::custom("missing `0x`-prefix"))?
35            .parse()
36            .map_err(de::Error::custom)
37    }
38}
39
40impl Serialize for Digest {
41    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42    where
43        S: Serializer,
44    {
45        let buffer = self.fmt_buffer(Default::default());
46        serializer.serialize_str(buffer.as_str())
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53    use serde::de::value::{self, BorrowedStrDeserializer};
54
55    #[test]
56    fn deserialize_digest() {
57        for s in [
58            "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
59            "0xeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeE",
60            "0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
61        ] {
62            let deserializer = BorrowedStrDeserializer::<value::Error>::new(s);
63            assert_eq!(
64                Digest::deserialize(deserializer).unwrap(),
65                Digest([0xee; 32]),
66            )
67        }
68    }
69
70    #[test]
71    fn deserialize_digest_requires_0x_prefix() {
72        let without_prefix = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
73        let deserializer = BorrowedStrDeserializer::<value::Error>::new(without_prefix);
74        assert!(Digest::deserialize(deserializer).is_err());
75    }
76}