ethereum_mysql/
macros.rs

1//! This module provides convenient macros for creating SqlAddress and SqlFixedBytes instances
2//! from string literals at compile time, similar to alloy's address! and fixed_bytes! macros.
3
4/// Creates a SqlAddress from a hex string literal.
5///
6/// This macro accepts hex strings with or without the "0x" prefix and creates
7/// a SqlAddress at compile time. The input is validated at compile time.
8///
9/// The macro supports both runtime and const contexts, making it suitable
10/// for declaring const SqlAddress values.
11///
12/// # Examples
13///
14/// ```
15/// use ethereum_mysql::{sqladdress, SqlAddress};
16///
17/// // With 0x prefix
18/// let addr1 = sqladdress!("0x742d35Cc6635C0532925a3b8D42cC72b5c2A9A1d");
19///
20/// // Without 0x prefix  
21/// let addr2 = sqladdress!("742d35Cc6635C0532925a3b8D42cC72b5c2A9A1d");
22///
23/// // Zero address
24/// let zero = sqladdress!("0x0000000000000000000000000000000000000000");
25///
26/// // Const context
27/// const ADMIN: SqlAddress = sqladdress!("0x742d35Cc6635C0532925a3b8D42cC72b5c2A9A1d");
28/// ```
29#[macro_export]
30macro_rules! sqladdress {
31    ($s:expr) => {
32        $crate::SqlAddress::new_from_address($crate::alloy::primitives::address!($s))
33    };
34}
35
36/// Macro to create a `SqlFixedBytes<N>` from a hex string literal at compile time.
37///
38/// Usage:
39/// ```
40/// use ethereum_mysql::{sqlhash, SqlFixedBytes};
41/// const HASH: SqlFixedBytes<32> = sqlhash!(32, "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef");
42/// const SHORT: SqlFixedBytes<4> = sqlhash!(4, "0x12345678");
43/// ```
44///
45/// N 必须是字面量(literal),与 hex 长度匹配,否则编译报错。
46#[macro_export]
47macro_rules! sqlhash {
48    ($n:literal, $s:literal) => {{
49        $crate::SqlFixedBytes::<$n>::from_bytes($crate::alloy::primitives::fixed_bytes!($s))
50    }};
51}
52/// Macro to create a SqlU256 from a literal (compile-time check for negative, only usable in runtime context).
53///
54/// Usage:
55/// let a: SqlU256 = sqlu256!(100); // OK
56/// let b: SqlU256 = sqlu256!(-100); // Compile error
57/// // const A: SqlU256 = sqlu256!(100); // ❌ Not supported: `From<u128>` is not const
58#[macro_export]
59macro_rules! sqlu256 {
60    ($val:literal) => {{
61        const _: () = assert!($val >= 0, "SqlU256 cannot be negative at compile time");
62        $crate::SqlU256::from($val as u128)
63    }};
64}
65
66#[cfg(test)]
67mod tests {
68    use crate::SqlHash;
69    use alloy::primitives::hex;
70
71    #[test]
72    fn test_sqlhash_const_and_runtime() {
73        // Const context
74        const TRANSFER_EVENT_SIGNATURE: SqlHash = sqlhash!(
75            32,
76            "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
77        );
78        // Runtime context
79        let runtime_hash: SqlHash = sqlhash!(
80            32,
81            "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
82        );
83        // Both should be equal
84        assert_eq!(TRANSFER_EVENT_SIGNATURE, runtime_hash);
85        // Should match expected bytes
86        let expected =
87            hex::decode("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
88                .unwrap();
89        assert_eq!(TRANSFER_EVENT_SIGNATURE.as_slice(), expected.as_slice());
90        // Shorter length test
91        const SHORT: crate::SqlFixedBytes<4> = sqlhash!(4, "0x095ea7b3");
92        let short_expected = hex::decode("095ea7b3").unwrap();
93        assert_eq!(SHORT.as_slice(), short_expected.as_slice());
94    }
95    #[test]
96    fn test_sqlu256_runtime() {
97        // Runtime context only
98        let runtime_amount: crate::SqlU256 = sqlu256!(12345678901234567890u128);
99        use alloy::primitives::U256;
100        let expected = U256::from(12345678901234567890u128);
101        assert_eq!(*runtime_amount, expected);
102    }
103}