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}