ethereum-mysql 4.0.0

Ethereum types (Address, U256) wrapper for seamless SQL database integration with SQLx
Documentation
//! Type conversion implementations for SqlUint types
//!
//! This module provides conversions from various integer types to SqlUint,
//! following Rust's standard library patterns.

use crate::{SqlU128, SqlU256, U128, U256};
use crate::error::SqlTypeError;

// Macro to reduce boilerplate for unsigned integer conversions
macro_rules! impl_from_unsigned_for {
    ($sql_ty:ty, $uint_ty:ty) => {
        impl From<u8> for $sql_ty {
            fn from(value: u8) -> Self {
                Self::from(<$uint_ty>::from(value))
            }
        }
        impl From<u16> for $sql_ty {
            fn from(value: u16) -> Self {
                Self::from(<$uint_ty>::from(value))
            }
        }
        impl From<u32> for $sql_ty {
            fn from(value: u32) -> Self {
                Self::from(<$uint_ty>::from(value))
            }
        }
        impl From<u64> for $sql_ty {
            fn from(value: u64) -> Self {
                Self::from(<$uint_ty>::from(value))
            }
        }
        impl From<u128> for $sql_ty {
            fn from(value: u128) -> Self {
                Self::from(<$uint_ty>::from(value))
            }
        }
        impl From<usize> for $sql_ty {
            fn from(value: usize) -> Self {
                Self::from(<$uint_ty>::from(value as u64))
            }
        }
    };
}

impl_from_unsigned_for!(SqlU128, U128);
impl_from_unsigned_for!(SqlU256, U256);

// Macro for signed integer TryFrom conversions
macro_rules! impl_try_from_signed_for {
    ($sql_ty:ty) => {
        impl TryFrom<i8> for $sql_ty {
            type Error = SqlTypeError;
            fn try_from(value: i8) -> Result<Self, Self::Error> {
                if value < 0 {
                    Err(SqlTypeError::NegativeValue)
                } else {
                    Ok(Self::from(value as u8))
                }
            }
        }
        impl TryFrom<i16> for $sql_ty {
            type Error = SqlTypeError;
            fn try_from(value: i16) -> Result<Self, Self::Error> {
                if value < 0 {
                    Err(SqlTypeError::NegativeValue)
                } else {
                    Ok(Self::from(value as u16))
                }
            }
        }
        impl TryFrom<i32> for $sql_ty {
            type Error = SqlTypeError;
            fn try_from(value: i32) -> Result<Self, Self::Error> {
                if value < 0 {
                    Err(SqlTypeError::NegativeValue)
                } else {
                    Ok(Self::from(value as u32))
                }
            }
        }
        impl TryFrom<i64> for $sql_ty {
            type Error = SqlTypeError;
            fn try_from(value: i64) -> Result<Self, Self::Error> {
                if value < 0 {
                    Err(SqlTypeError::NegativeValue)
                } else {
                    Ok(Self::from(value as u64))
                }
            }
        }
        impl TryFrom<i128> for $sql_ty {
            type Error = SqlTypeError;
            fn try_from(value: i128) -> Result<Self, Self::Error> {
                if value < 0 {
                    Err(SqlTypeError::NegativeValue)
                } else {
                    Ok(Self::from(value as u128))
                }
            }
        }
        impl TryFrom<isize> for $sql_ty {
            type Error = SqlTypeError;
            fn try_from(value: isize) -> Result<Self, Self::Error> {
                if value < 0 {
                    Err(SqlTypeError::NegativeValue)
                } else {
                    Ok(Self::from(value as u64))
                }
            }
        }
    };
}

impl_try_from_signed_for!(SqlU128);
impl_try_from_signed_for!(SqlU256);

// Macro for SqlUint to smaller integer TryFrom conversions
macro_rules! impl_try_from_sql_uint_to {
    ($sql_ty:ty, $max_ty:ty) => {
        impl TryFrom<$sql_ty> for u8 {
            type Error = SqlTypeError;
            fn try_from(value: $sql_ty) -> Result<Self, Self::Error> {
                let inner: $max_ty = value.into();
                if inner > <$max_ty>::from(u8::MAX) {
                    Err(SqlTypeError::Overflow)
                } else {
                    Ok(inner.to::<u8>())
                }
            }
        }
        impl TryFrom<$sql_ty> for u16 {
            type Error = SqlTypeError;
            fn try_from(value: $sql_ty) -> Result<Self, Self::Error> {
                let inner: $max_ty = value.into();
                if inner > <$max_ty>::from(u16::MAX) {
                    Err(SqlTypeError::Overflow)
                } else {
                    Ok(inner.to::<u16>())
                }
            }
        }
        impl TryFrom<$sql_ty> for u32 {
            type Error = SqlTypeError;
            fn try_from(value: $sql_ty) -> Result<Self, Self::Error> {
                let inner: $max_ty = value.into();
                if inner > <$max_ty>::from(u32::MAX) {
                    Err(SqlTypeError::Overflow)
                } else {
                    Ok(inner.to::<u32>())
                }
            }
        }
        impl TryFrom<$sql_ty> for u64 {
            type Error = SqlTypeError;
            fn try_from(value: $sql_ty) -> Result<Self, Self::Error> {
                let inner: $max_ty = value.into();
                if inner > <$max_ty>::from(u64::MAX) {
                    Err(SqlTypeError::Overflow)
                } else {
                    Ok(inner.to::<u64>())
                }
            }
        }
        impl TryFrom<$sql_ty> for u128 {
            type Error = SqlTypeError;
            fn try_from(value: $sql_ty) -> Result<Self, Self::Error> {
                let inner: $max_ty = value.into();
                if inner > <$max_ty>::from(u128::MAX) {
                    Err(SqlTypeError::Overflow)
                } else {
                    Ok(inner.to::<u128>())
                }
            }
        }
        impl TryFrom<$sql_ty> for usize {
            type Error = SqlTypeError;
            fn try_from(value: $sql_ty) -> Result<Self, Self::Error> {
                let inner: $max_ty = value.into();
                if inner > <$max_ty>::from(u64::MAX) {
                    Err(SqlTypeError::Overflow)
                } else {
                    Ok(inner.to::<u64>() as usize)
                }
            }
        }
    };
}

impl_try_from_sql_uint_to!(SqlU128, U128);
impl_try_from_sql_uint_to!(SqlU256, U256);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_from_unsigned_integers_u256() {
        assert_eq!(SqlU256::from(42u8), SqlU256::from(U256::from(42)));
        assert_eq!(SqlU256::from(1000u16), SqlU256::from(U256::from(1000)));
        assert_eq!(SqlU256::from(100000u32), SqlU256::from(U256::from(100000)));
        assert_eq!(
            SqlU256::from(10000000000u64),
            SqlU256::from(U256::from(10000000000u64))
        );
        assert_eq!(
            SqlU256::from(u128::MAX),
            SqlU256::from(U256::from(u128::MAX))
        );
        assert_eq!(SqlU256::from(123usize), SqlU256::from(U256::from(123)));
    }

    #[test]
    fn test_from_unsigned_integers_u128() {
        assert_eq!(SqlU128::from(42u8), SqlU128::from(U128::from(42)));
        assert_eq!(SqlU128::from(1000u16), SqlU128::from(U128::from(1000)));
        assert_eq!(SqlU128::from(100000u32), SqlU128::from(U128::from(100000)));
        assert_eq!(
            SqlU128::from(u64::MAX),
            SqlU128::from(U128::from(u64::MAX))
        );
        assert_eq!(SqlU128::from(123usize), SqlU128::from(U128::from(123)));
    }

    #[test]
    fn test_try_from_positive_signed_integers_u256() {
        assert_eq!(
            SqlU256::try_from(42i8).unwrap(),
            SqlU256::from(U256::from(42))
        );
        assert_eq!(
            SqlU256::try_from(1000i16).unwrap(),
            SqlU256::from(U256::from(1000))
        );
        assert_eq!(
            SqlU256::try_from(100000i32).unwrap(),
            SqlU256::from(U256::from(100000))
        );
        assert_eq!(
            SqlU256::try_from(10000000000i64).unwrap(),
            SqlU256::from(U256::from(10000000000u64))
        );
        assert_eq!(
            SqlU256::try_from(i128::MAX).unwrap(),
            SqlU256::from(U256::from(i128::MAX as u128))
        );
        assert_eq!(
            SqlU256::try_from(123isize).unwrap(),
            SqlU256::from(U256::from(123))
        );
    }

    #[test]
    fn test_try_from_negative_signed_integers_u256() {
        assert!(SqlU256::try_from(-1i8).is_err());
        assert!(SqlU256::try_from(-1000i16).is_err());
        assert!(SqlU256::try_from(-100000i32).is_err());
        assert!(SqlU256::try_from(-10000000000i64).is_err());
        assert!(SqlU256::try_from(i128::MIN).is_err());
        assert!(SqlU256::try_from(-123isize).is_err());
    }

    #[test]
    fn test_try_from_sql_uint_to_smaller_types_u256() {
        let small_value = SqlU256::from(42u8);
        assert_eq!(u8::try_from(small_value).unwrap(), 42u8);
        assert_eq!(u16::try_from(small_value).unwrap(), 42u16);
        assert_eq!(u32::try_from(small_value).unwrap(), 42u32);
        assert_eq!(u64::try_from(small_value).unwrap(), 42u64);
        assert_eq!(u128::try_from(small_value).unwrap(), 42u128);
        assert_eq!(usize::try_from(small_value).unwrap(), 42usize);

        let large_value = SqlU256::from(u64::MAX);
        assert!(u8::try_from(large_value).is_err());
        assert!(u16::try_from(large_value).is_err());
        assert!(u32::try_from(large_value).is_err());
        assert_eq!(u64::try_from(large_value).unwrap(), u64::MAX);

        let very_large = SqlU256::from(U256::from(u128::MAX));
        assert!(u64::try_from(very_large).is_err());
        assert_eq!(u128::try_from(very_large).unwrap(), u128::MAX);
    }

    #[test]
    fn test_conversion_chain_u256() {
        let value: SqlU256 = 42u64.into();
        assert_eq!(value, SqlU256::from(U256::from(42)));
        let back: u64 = value.try_into().unwrap();
        assert_eq!(back, 42u64);
    }

    #[test]
    fn test_conversion_chain_u128() {
        let value: SqlU128 = 42u64.into();
        assert_eq!(value, SqlU128::from(U128::from(42)));
        let back: u64 = value.try_into().unwrap();
        assert_eq!(back, 42u64);
    }
}