neo_web3/types/
bytes.rs

1use serde::{
2    de::{Error, Unexpected, Visitor},
3    Deserialize, Deserializer, Serialize, Serializer,
4};
5use std::fmt;
6
7/// Raw bytes wrapper
8#[derive(Clone, Default, PartialEq, Eq, Hash)]
9pub struct Bytes(pub Vec<u8>);
10
11impl<T: Into<Vec<u8>>> From<T> for Bytes {
12    fn from(data: T) -> Self {
13        Bytes(data.into())
14    }
15}
16
17impl Serialize for Bytes {
18    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
19    where
20        S: Serializer,
21    {
22        let mut serialized = "0x".to_owned();
23        serialized.push_str(&hex::encode(&self.0));
24        serializer.serialize_str(serialized.as_ref())
25    }
26}
27
28impl<'a> Deserialize<'a> for Bytes {
29    fn deserialize<D>(deserializer: D) -> Result<Bytes, D::Error>
30    where
31        D: Deserializer<'a>,
32    {
33        deserializer.deserialize_identifier(BytesVisitor)
34    }
35}
36
37impl fmt::Debug for Bytes {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        let serialized = format!("0x{}", hex::encode(&self.0));
40        f.debug_tuple("Bytes").field(&serialized).finish()
41    }
42}
43
44struct BytesVisitor;
45
46impl<'a> Visitor<'a> for BytesVisitor {
47    type Value = Bytes;
48
49    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50        write!(formatter, "a 0x-prefixed hex-encoded vector of bytes")
51    }
52
53    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
54    where
55        E: Error,
56    {
57        if let Some(value) = value.strip_prefix("0x") {
58            let bytes = hex::decode(value).map_err(|e| Error::custom(format!("Invalid hex: {}", e)))?;
59            Ok(Bytes(bytes))
60        } else {
61            Err(Error::invalid_value(Unexpected::Str(value), &"0x prefix"))
62        }
63    }
64
65    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
66    where
67        E: Error,
68    {
69        self.visit_str(value.as_ref())
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn deserialize() {
79        assert_eq!(serde_json::from_str::<Bytes>(r#""0x00""#).unwrap(), Bytes(vec![0x00]));
80        assert_eq!(
81            serde_json::from_str::<Bytes>(r#""0x0123456789AaBbCcDdEeFf""#).unwrap(),
82            Bytes(vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF])
83        );
84        assert_eq!(serde_json::from_str::<Bytes>(r#""0x""#).unwrap(), Bytes(vec![]));
85
86        assert!(serde_json::from_str::<Bytes>("0").is_err(), "Not a string");
87        assert!(serde_json::from_str::<Bytes>(r#""""#).is_err(), "Empty string");
88        assert!(serde_json::from_str::<Bytes>(r#""0xZZ""#).is_err(), "Invalid hex");
89        assert!(
90            serde_json::from_str::<Bytes>(r#""deadbeef""#).is_err(),
91            "Missing 0x prefix"
92        );
93        assert!(serde_json::from_str::<Bytes>(r#""数字""#).is_err(), "Non-ASCII");
94        assert!(serde_json::from_str::<Bytes>(r#""0x数字""#).is_err(), "Non-ASCII");
95    }
96}