blockscout_display_bytes/
bytes.rs

1/// Adapted from ethers-core (https://github.com/gakonst/ethers-rs/blob/master/ethers-core/src/types/bytes.rs)
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::{
4    borrow::Borrow,
5    clone::Clone,
6    fmt::{Debug, Display, Formatter, LowerHex, Result as FmtResult},
7    ops::Deref,
8    str::FromStr,
9};
10use thiserror::Error;
11
12/// Wrapper type around Bytes to deserialize/serialize "0x" prefixed ethereum hex strings
13#[derive(Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
14pub struct Bytes(
15    #[serde(
16        serialize_with = "serialize_bytes",
17        deserialize_with = "deserialize_bytes"
18    )]
19    pub bytes::Bytes,
20);
21
22fn bytes_to_hex(b: &Bytes) -> String {
23    hex::encode(b.0.as_ref())
24}
25
26impl Debug for Bytes {
27    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
28        write!(f, "Bytes(0x{})", bytes_to_hex(self))
29    }
30}
31
32impl Display for Bytes {
33    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
34        write!(f, "0x{}", bytes_to_hex(self))
35    }
36}
37
38impl LowerHex for Bytes {
39    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
40        write!(f, "0x{}", bytes_to_hex(self))
41    }
42}
43
44impl Bytes {
45    pub fn to_vec(&self) -> Vec<u8> {
46        self.as_ref().to_vec()
47    }
48}
49
50impl Deref for Bytes {
51    type Target = [u8];
52
53    #[inline]
54    fn deref(&self) -> &[u8] {
55        self.as_ref()
56    }
57}
58
59impl AsRef<[u8]> for Bytes {
60    fn as_ref(&self) -> &[u8] {
61        self.0.as_ref()
62    }
63}
64
65impl Borrow<[u8]> for Bytes {
66    fn borrow(&self) -> &[u8] {
67        self.as_ref()
68    }
69}
70
71impl IntoIterator for Bytes {
72    type Item = u8;
73    type IntoIter = bytes::buf::IntoIter<bytes::Bytes>;
74
75    fn into_iter(self) -> Self::IntoIter {
76        self.0.into_iter()
77    }
78}
79
80impl<'a> IntoIterator for &'a Bytes {
81    type Item = &'a u8;
82    type IntoIter = core::slice::Iter<'a, u8>;
83
84    fn into_iter(self) -> Self::IntoIter {
85        self.as_ref().iter()
86    }
87}
88
89impl From<bytes::Bytes> for Bytes {
90    fn from(src: bytes::Bytes) -> Self {
91        Self(src)
92    }
93}
94
95impl From<Vec<u8>> for Bytes {
96    fn from(src: Vec<u8>) -> Self {
97        Self(src.into())
98    }
99}
100
101impl<const N: usize> From<[u8; N]> for Bytes {
102    fn from(src: [u8; N]) -> Self {
103        src.to_vec().into()
104    }
105}
106
107impl<'a, const N: usize> From<&'a [u8; N]> for Bytes {
108    fn from(src: &'a [u8; N]) -> Self {
109        src.to_vec().into()
110    }
111}
112
113impl PartialEq<[u8]> for Bytes {
114    fn eq(&self, other: &[u8]) -> bool {
115        self.as_ref() == other
116    }
117}
118
119impl PartialEq<Bytes> for [u8] {
120    fn eq(&self, other: &Bytes) -> bool {
121        *other == *self
122    }
123}
124
125impl PartialEq<Vec<u8>> for Bytes {
126    fn eq(&self, other: &Vec<u8>) -> bool {
127        self.as_ref() == &other[..]
128    }
129}
130
131impl PartialEq<Bytes> for Vec<u8> {
132    fn eq(&self, other: &Bytes) -> bool {
133        *other == *self
134    }
135}
136
137impl PartialEq<bytes::Bytes> for Bytes {
138    fn eq(&self, other: &bytes::Bytes) -> bool {
139        other == self.as_ref()
140    }
141}
142
143#[derive(Debug, Clone, Error)]
144#[error("Failed to parse bytes: {0}")]
145pub struct ParseBytesError(String);
146
147impl FromStr for Bytes {
148    type Err = ParseBytesError;
149
150    fn from_str(value: &str) -> Result<Self, Self::Err> {
151        super::decode_hex(value)
152            .map(Into::into)
153            .map_err(|e| ParseBytesError(format!("Invalid hex: {e}")))
154    }
155}
156
157pub fn serialize_bytes<S, T>(x: T, s: S) -> Result<S::Ok, S::Error>
158where
159    S: Serializer,
160    T: AsRef<[u8]>,
161{
162    s.serialize_str(&format!("0x{}", hex::encode(x.as_ref())))
163}
164
165pub fn deserialize_bytes<'de, D>(d: D) -> Result<bytes::Bytes, D::Error>
166where
167    D: Deserializer<'de>,
168{
169    let value = String::deserialize(d)?;
170    super::decode_hex(&value)
171        .map(Into::into)
172        .map_err(|e| serde::de::Error::custom(e.to_string()))
173}
174
175#[cfg(test)]
176mod tests {
177    use super::*;
178
179    #[test]
180    fn hex_formatting() {
181        let b = Bytes::from(vec![1, 35, 69, 103, 137, 171, 205, 239]);
182        let expected = String::from("0x0123456789abcdef");
183        assert_eq!(format!("{b:x}"), expected);
184        assert_eq!(format!("{b}"), expected);
185    }
186
187    #[test]
188    fn test_from_str() {
189        let b = Bytes::from_str("0x1213");
190        assert!(b.is_ok());
191        let b = b.unwrap();
192        assert_eq!(b.as_ref(), hex::decode("1213").unwrap());
193
194        let b = Bytes::from_str("1213");
195        let b = b.unwrap();
196        assert_eq!(b.as_ref(), hex::decode("1213").unwrap());
197    }
198
199    #[test]
200    fn test_debug_formatting() {
201        let b = Bytes::from(vec![1, 35, 69, 103, 137, 171, 205, 239]);
202        assert_eq!(format!("{b:?}"), "Bytes(0x0123456789abcdef)");
203        assert_eq!(format!("{b:#?}"), "Bytes(0x0123456789abcdef)");
204    }
205}