use crate::{SqlU128, SqlU256, U128, U256};
use crate::error::SqlTypeError;
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_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_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);
}
}