ethereum_mysql/
sql_bytes.rs

1pub use alloy::primitives::Bytes;
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4use std::ops::Deref;
5use std::str::FromStr;
6
7/// A wrapper around `Bytes` to represent SQL byte arrays.
8#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct SqlBytes(Bytes);
11
12impl SqlBytes {
13    /// Creates a new `SqlBytes` initialized to zero.
14    pub fn new() -> Self {
15        SqlBytes(Bytes::new())
16    }
17
18    /// Returns a reference to the inner `Bytes`.
19    pub fn inner(&self) -> &Bytes {
20        &self.0
21    }
22
23    /// Converts the bytes to a SqlU256 using big-endian interpretation.
24    ///
25    /// If the length is less than 32, left-pads with zeros; if more, truncates high bytes (alloy behavior).
26    pub fn to_u256(&self) -> crate::SqlU256 {
27        crate::SqlU256::from(alloy::primitives::U256::from_be_slice(self.as_ref()))
28    }
29}
30
31impl AsRef<Bytes> for SqlBytes {
32    /// Returns a reference to the inner Bytes.
33    fn as_ref(&self) -> &Bytes {
34        &self.0
35    }
36}
37
38impl Deref for SqlBytes {
39    type Target = Bytes;
40
41    /// Dereferences to the inner Bytes, allowing direct access to Bytes methods.
42    ///
43    /// This enables calling any method available on `alloy::primitives::Bytes`
44    /// directly on a `SqlBytes` instance.
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49
50impl From<Bytes> for SqlBytes {
51    fn from(bytes: Bytes) -> Self {
52        SqlBytes(bytes)
53    }
54}
55
56impl From<SqlBytes> for Bytes {
57    fn from(sql_bytes: SqlBytes) -> Self {
58        sql_bytes.0
59    }
60}
61
62impl std::fmt::Display for SqlBytes {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        write!(f, "{}", self.0.to_string().to_lowercase())
65    }
66}
67
68impl FromStr for SqlBytes {
69    type Err = <Bytes as FromStr>::Err;
70
71    fn from_str(s: &str) -> Result<Self, Self::Err> {
72        Bytes::from_str(s).map(SqlBytes)
73    }
74}
75
76impl Default for SqlBytes {
77    fn default() -> Self {
78        SqlBytes::new()
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_display() {
88        let sql_bytes = SqlBytes::from_str("0x1234").unwrap();
89        assert_eq!(format!("{}", sql_bytes), "0x1234");
90    }
91
92    #[cfg(feature = "serde")]
93    #[test]
94    fn test_serde() {
95        let input = "0xa9059cbb00000000000000000000000042066a09b94e41e0263eee935177c2ecfff7fe11000000000000000000000000000000000000000000000002629f66e0c5300000";
96        let val = SqlBytes::from_str(input).unwrap();
97        let json = serde_json::to_string(&val).unwrap();
98        let de: SqlBytes = serde_json::from_str(&json).unwrap();
99        assert_eq!(val, de);
100    }
101}