ethereum_mysql/sql_uint/
convert.rs

1//! Type conversion implementations for SqlU256
2//!
3//! This module provides conversions from various integer types to SqlU256,
4//! following Rust's standard library patterns.
5
6use crate::{SqlU256, U256};
7
8// Macro to reduce boilerplate for unsigned integer conversions
9macro_rules! impl_from_unsigned {
10    ($($t:ty),*) => {
11        $(
12            impl From<$t> for SqlU256 {
13                fn from(value: $t) -> Self {
14                    SqlU256::from(U256::from(value))
15                }
16            }
17        )*
18    };
19}
20
21// Implement From for all unsigned integer types
22impl_from_unsigned!(u8, u16, u32, u64, u128);
23
24impl From<usize> for SqlU256 {
25    fn from(value: usize) -> Self {
26        SqlU256::from(U256::from(value as u64))
27    }
28}
29
30// Macro to reduce boilerplate for signed integer TryFrom conversions
31macro_rules! impl_try_from_signed {
32    ($($t:ty => $cast:ty),*) => {
33        $(
34            impl TryFrom<$t> for SqlU256 {
35                type Error = &'static str;
36
37                fn try_from(value: $t) -> Result<Self, Self::Error> {
38                    if value < 0 {
39                        Err("Cannot convert negative value to SqlU256")
40                    } else {
41                        Ok(SqlU256::from(U256::from(value as $cast)))
42                    }
43                }
44            }
45        )*
46    };
47}
48
49// Implement TryFrom for all signed integer types
50impl_try_from_signed!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128);
51
52impl TryFrom<isize> for SqlU256 {
53    type Error = &'static str;
54
55    fn try_from(value: isize) -> Result<Self, Self::Error> {
56        if value < 0 {
57            Err("Cannot convert negative value to SqlU256")
58        } else {
59            Ok(SqlU256::from(U256::from(value as u64)))
60        }
61    }
62}
63
64// Macro to reduce boilerplate for SqlU256 to smaller integer TryFrom conversions
65macro_rules! impl_try_from_sql_u256 {
66    ($($t:ty),*) => {
67        $(
68            impl TryFrom<SqlU256> for $t {
69                type Error = &'static str;
70
71                fn try_from(value: SqlU256) -> Result<Self, Self::Error> {
72                    if value.0 > U256::from(<$t>::MAX) {
73                        Err(concat!("SqlU256 value too large for ", stringify!($t)))
74                    } else {
75                        Ok(value.0.to::<$t>())
76                    }
77                }
78            }
79        )*
80    };
81}
82
83// Implement TryFrom for all smaller integer types
84impl_try_from_sql_u256!(u8, u16, u32, u64, u128);
85
86impl TryFrom<SqlU256> for usize {
87    type Error = &'static str;
88
89    fn try_from(value: SqlU256) -> Result<Self, Self::Error> {
90        if value.0 > U256::from(u64::MAX) {
91            Err("SqlU256 value too large for usize")
92        } else {
93            Ok(value.0.to::<u64>() as usize)
94        }
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_from_unsigned_integers() {
104        assert_eq!(SqlU256::from(42u8), SqlU256::from(U256::from(42)));
105        assert_eq!(SqlU256::from(1000u16), SqlU256::from(U256::from(1000)));
106        assert_eq!(SqlU256::from(100000u32), SqlU256::from(U256::from(100000)));
107        assert_eq!(
108            SqlU256::from(10000000000u64),
109            SqlU256::from(U256::from(10000000000u64))
110        );
111        assert_eq!(
112            SqlU256::from(u128::MAX),
113            SqlU256::from(U256::from(u128::MAX))
114        );
115        assert_eq!(SqlU256::from(123usize), SqlU256::from(U256::from(123)));
116    }
117
118    #[test]
119    fn test_try_from_positive_signed_integers() {
120        assert_eq!(
121            SqlU256::try_from(42i8).unwrap(),
122            SqlU256::from(U256::from(42))
123        );
124        assert_eq!(
125            SqlU256::try_from(1000i16).unwrap(),
126            SqlU256::from(U256::from(1000))
127        );
128        assert_eq!(
129            SqlU256::try_from(100000i32).unwrap(),
130            SqlU256::from(U256::from(100000))
131        );
132        assert_eq!(
133            SqlU256::try_from(10000000000i64).unwrap(),
134            SqlU256::from(U256::from(10000000000u64))
135        );
136        assert_eq!(
137            SqlU256::try_from(i128::MAX).unwrap(),
138            SqlU256::from(U256::from(i128::MAX as u128))
139        );
140        assert_eq!(
141            SqlU256::try_from(123isize).unwrap(),
142            SqlU256::from(U256::from(123))
143        );
144    }
145
146    #[test]
147    fn test_try_from_negative_signed_integers() {
148        assert!(SqlU256::try_from(-1i8).is_err());
149        assert!(SqlU256::try_from(-1000i16).is_err());
150        assert!(SqlU256::try_from(-100000i32).is_err());
151        assert!(SqlU256::try_from(-10000000000i64).is_err());
152        assert!(SqlU256::try_from(i128::MIN).is_err());
153        assert!(SqlU256::try_from(-123isize).is_err());
154    }
155
156    #[test]
157    fn test_try_from_sql_u256_to_smaller_types() {
158        // Test successful conversions
159        let small_value = SqlU256::from(42u8);
160        assert_eq!(u8::try_from(small_value).unwrap(), 42u8);
161        assert_eq!(u16::try_from(small_value).unwrap(), 42u16);
162        assert_eq!(u32::try_from(small_value).unwrap(), 42u32);
163        assert_eq!(u64::try_from(small_value).unwrap(), 42u64);
164        assert_eq!(u128::try_from(small_value).unwrap(), 42u128);
165        assert_eq!(usize::try_from(small_value).unwrap(), 42usize);
166
167        // Test overflow cases
168        let large_value = SqlU256::from(u64::MAX);
169        assert!(u8::try_from(large_value).is_err());
170        assert!(u16::try_from(large_value).is_err());
171        assert!(u32::try_from(large_value).is_err());
172        assert_eq!(u64::try_from(large_value).unwrap(), u64::MAX);
173
174        // Test very large value
175        let very_large = SqlU256::from(U256::from(u128::MAX));
176        assert!(u64::try_from(very_large).is_err());
177        assert_eq!(u128::try_from(very_large).unwrap(), u128::MAX);
178    }
179
180    #[test]
181    fn test_conversion_chain() {
182        // Test that we can chain conversions naturally
183        let value: SqlU256 = 42u64.into();
184        assert_eq!(value, SqlU256::from(U256::from(42)));
185
186        let back: u64 = value.try_into().unwrap();
187        assert_eq!(back, 42u64);
188    }
189}