ethane_types/
bytes.rs

1use serde::de::Visitor;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::convert::TryFrom;
4
5/// A type for hex values of arbitrary length
6#[derive(Clone, Debug, PartialEq, Default)]
7pub struct Bytes(pub Vec<u8>);
8
9impl Bytes {
10    pub fn from_slice(slice: &[u8]) -> Self {
11        Bytes(slice.to_vec())
12    }
13}
14
15impl TryFrom<&str> for Bytes {
16    type Error = String;
17
18    fn try_from(value: &str) -> Result<Self, Self::Error> {
19        let trimmed = value.trim_start_matches("0x");
20        let length = trimmed.len();
21        let end = if length % 2 == 0 {
22            length / 2
23        } else {
24            length / 2 + 1
25        };
26        let mut data = Vec::<u8>::with_capacity(end);
27        let mut trimmed_chars = trimmed.chars();
28        for _ in 0..end {
29            let first = trimmed_chars
30                .next()
31                .unwrap()
32                .to_digit(16)
33                .ok_or_else(|| String::from("invalid digit found in string"))?;
34            let second = if let Some(sec) = trimmed_chars.next() {
35                sec.to_digit(16)
36                    .ok_or_else(|| String::from("invalid digit found in string"))?
37            } else {
38                0
39            };
40            data.push((first * 16 + second) as u8)
41        }
42        Ok(Self(data))
43    }
44}
45
46impl std::fmt::Display for Bytes {
47    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        write!(
49            formatter,
50            "0x{}",
51            self.0
52                .iter()
53                .map(|b| format!("{:02x}", b))
54                .collect::<Vec<String>>()
55                .join("")
56        )
57    }
58}
59
60impl Serialize for Bytes {
61    fn serialize<T: Serializer>(&self, serializer: T) -> Result<T::Ok, T::Error> {
62        serializer.serialize_str(&self.to_string())
63    }
64}
65
66impl<'de> Deserialize<'de> for Bytes {
67    fn deserialize<T>(deserializer: T) -> Result<Bytes, T::Error>
68    where
69        T: Deserializer<'de>,
70    {
71        deserializer.deserialize_identifier(BytesVisitor)
72    }
73}
74
75struct BytesVisitor;
76
77impl<'de> Visitor<'de> for BytesVisitor {
78    type Value = Bytes;
79
80    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
81        write!(f, "a hex string")
82    }
83
84    fn visit_str<T: serde::de::Error>(self, value: &str) -> Result<Self::Value, T> {
85        let result = Self::Value::try_from(value)
86            .map_err(|err| serde::de::Error::custom(format!("Invalid hex string: {}", err)))?;
87        Ok(result)
88    }
89
90    fn visit_string<T: serde::de::Error>(self, value: String) -> Result<Self::Value, T> {
91        self.visit_str(&value)
92    }
93}
94
95#[test]
96fn test_bytes() {
97    let bytes_0 = Bytes::from_slice(&[]);
98    let bytes_1 = Bytes::from_slice(&[0, 0]);
99    let bytes_2 = Bytes::from_slice(&[17, 234]);
100    let bytes_3 = Bytes::try_from("0x").unwrap();
101    let bytes_4 = Bytes::try_from("0x00").unwrap();
102    let bytes_5 = Bytes::try_from("00421100").unwrap();
103
104    let expected_0 = "0x";
105    let expected_1 = "0x0000";
106    let expected_2 = "0x11ea";
107    let expected_3 = Bytes(vec![]);
108    let expected_4 = Bytes(vec![0]);
109    let expected_5 = Bytes(vec![0, 66, 17, 0]);
110
111    serde_test::assert_tokens(&bytes_0, &[serde_test::Token::BorrowedStr(expected_0)]);
112    serde_test::assert_tokens(&bytes_1, &[serde_test::Token::BorrowedStr(expected_1)]);
113    serde_test::assert_tokens(&bytes_2, &[serde_test::Token::BorrowedStr(expected_2)]);
114    assert_eq!(bytes_3, expected_3);
115    assert_eq!(bytes_4, expected_4);
116    assert_eq!(bytes_5, expected_5);
117}