chia_serde/
lib.rs

1use std::fmt;
2
3use serde::{
4    de::{self, Visitor},
5    Deserializer, Serializer,
6};
7
8pub fn ser_bytes<S>(value: &[u8], serializer: S, include_0x: bool) -> Result<S::Ok, S::Error>
9where
10    S: Serializer,
11{
12    if serializer.is_human_readable() {
13        if include_0x {
14            serializer.serialize_str(&format!("0x{}", hex::encode(value)))
15        } else {
16            serializer.serialize_str(&hex::encode(value))
17        }
18    } else {
19        serializer.serialize_bytes(value)
20    }
21}
22
23pub fn de_bytes<'de, D, T>(deserializer: D) -> Result<T, D::Error>
24where
25    D: Deserializer<'de>,
26    T: TryFrom<Vec<u8>>,
27{
28    if deserializer.is_human_readable() {
29        struct HexOrBytesVisitor;
30
31        impl Visitor<'_> for HexOrBytesVisitor {
32            type Value = Vec<u8>;
33
34            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
35                formatter.write_str("a byte buffer or hex string with an optional 0x prefix")
36            }
37
38            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> {
39                Ok(v.to_vec())
40            }
41
42            fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> {
43                Ok(v)
44            }
45
46            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
47            where
48                E: de::Error,
49            {
50                if let Some(rest) = v.strip_prefix("0x") {
51                    Ok(hex::decode(rest).map_err(de::Error::custom)?)
52                } else if let Some(rest) = v.strip_prefix("0X") {
53                    Ok(hex::decode(rest).map_err(de::Error::custom)?)
54                } else {
55                    Ok(hex::decode(v).map_err(de::Error::custom)?)
56                }
57            }
58
59            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
60            where
61                E: de::Error,
62            {
63                self.visit_str(&v)
64            }
65        }
66
67        let bytes = deserializer.deserialize_any(HexOrBytesVisitor)?;
68        let length = bytes.len();
69
70        bytes.try_into().map_err(|_: T::Error| {
71            de::Error::custom(format_args!(
72                "Can't convert a byte buffer of length {length} to the output type."
73            ))
74        })
75    } else {
76        struct BytesVisitor;
77
78        impl Visitor<'_> for BytesVisitor {
79            type Value = Vec<u8>;
80
81            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
82                formatter.write_str("a byte buffer")
83            }
84
85            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> {
86                Ok(v.to_vec())
87            }
88
89            fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> {
90                Ok(v)
91            }
92        }
93
94        let bytes = deserializer.deserialize_byte_buf(BytesVisitor)?;
95        let length = bytes.len();
96
97        bytes.try_into().map_err(|_: T::Error| {
98            de::Error::custom(format_args!(
99                "Can't convert a byte buffer of length {length} to the output type."
100            ))
101        })
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    use anyhow::Result;
110
111    #[test]
112    fn test_encode_hex() -> Result<()> {
113        let original = b"hello";
114
115        let mut ser = serde_json::Serializer::new(Vec::new());
116        ser_bytes(original, &mut ser, false)?;
117        let result = String::from_utf8(ser.into_inner())?;
118        assert_eq!(result, "\"68656c6c6f\"");
119
120        let mut de = serde_json::Deserializer::from_str(&result);
121        let bytes = de_bytes::<_, Vec<u8>>(&mut de)?;
122        assert_eq!(bytes, original);
123
124        Ok(())
125    }
126
127    #[test]
128    fn test_encode_0x() -> Result<()> {
129        let original = b"hello";
130
131        let mut ser = serde_json::Serializer::new(Vec::new());
132        ser_bytes(original, &mut ser, true)?;
133        let result = String::from_utf8(ser.into_inner())?;
134        assert_eq!(result, "\"0x68656c6c6f\"");
135
136        let mut de = serde_json::Deserializer::from_str(&result);
137        let bytes = de_bytes::<_, Vec<u8>>(&mut de)?;
138        assert_eq!(bytes, original);
139
140        Ok(())
141    }
142
143    #[test]
144    fn test_encode_binary() -> Result<()> {
145        let original = b"hello";
146
147        let mut output = Vec::new();
148        let mut ser = bincode::Serializer::new(&mut output, bincode::options());
149        ser_bytes(original, &mut ser, true)?;
150        assert_eq!(hex::encode(&output), "0568656c6c6f");
151
152        let mut de = bincode::Deserializer::from_slice(&output, bincode::options());
153        let bytes = de_bytes::<_, Vec<u8>>(&mut de)?;
154        assert_eq!(bytes, original);
155
156        Ok(())
157    }
158}