1use 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}