From d52e8c377ff7da061b854293717e05e4fdc404ec Mon Sep 17 00:00:00 2001 From: Rajas Paranjpe <52586855+ChocolateLoverRaj@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:56:14 -0800 Subject: [PATCH] Add TryFrom for fallible conversions while implementing From for infallible conversions --- src/common.rs | 49 +++++++++++++++++++++++++++++++++-- src/signed.rs | 27 ++++++++++++++----- src/unsigned.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 129 insertions(+), 16 deletions(-) diff --git a/src/common.rs b/src/common.rs index 994ebef..6ec1424 100644 --- a/src/common.rs +++ b/src/common.rs @@ -46,7 +46,30 @@ macro_rules! from_arbitrary_int_impl { pub(crate) use from_arbitrary_int_impl; -macro_rules! from_native_impl { +macro_rules! from_native_bigger_impl { + ($ty:ident($from:ty), [$($into:ty),+]) => { + $( + impl TryFrom<$from> for $ty<$into, BITS> { + type Error = TryNewError; + + #[inline] + fn try_from(from: $from) -> Result { + Self::try_new(from.try_into().map_err(|_| TryNewError)?) + } + } + + impl From<$ty<$from, BITS>> for $into { + #[inline] + fn from(from: $ty<$from, BITS>) -> Self { + from.value as $into + } + } + )+ + }; +} +pub(crate) use from_native_bigger_impl; + +macro_rules! from_native_equal_impl { ($ty:ident($from:ty), [$($into:ty),+]) => { $( impl From<$from> for $ty<$into, BITS> { @@ -67,8 +90,30 @@ macro_rules! from_native_impl { )+ }; } +pub(crate) use from_native_equal_impl; + +macro_rules! from_native_smaller_impl { + ($ty:ident($from:ty), [$($into:ty),+]) => { + $( + impl From<$from> for $ty<$into, BITS> { + #[inline] + fn from(from: $from) -> Self { + Self { value: from.into() } + } + } + + impl TryFrom<$ty<$from, BITS>> for $into { + type Error = TryNewError; -pub(crate) use from_native_impl; + #[inline] + fn try_from(from: $ty<$from, BITS>) -> Result { + from.value.try_into().map_err(|_| TryNewError) + } + } + )+ + }; +} +pub(crate) use from_native_smaller_impl; macro_rules! impl_extract { ( diff --git a/src/signed.rs b/src/signed.rs index 89ef51c..5075c83 100644 --- a/src/signed.rs +++ b/src/signed.rs @@ -1,7 +1,8 @@ use crate::{ common::{ - bytes_operation_impl, from_arbitrary_int_impl, from_native_impl, impl_bin_proto, - impl_extract, impl_num_traits, impl_schemars, impl_step, impl_sum_product, + bytes_operation_impl, from_arbitrary_int_impl, from_native_bigger_impl, + from_native_equal_impl, from_native_smaller_impl, impl_bin_proto, impl_extract, + impl_num_traits, impl_schemars, impl_step, impl_sum_product, }, traits::{sealed::Sealed, BuiltinInteger, Integer, SignedInteger}, TryNewError, @@ -1964,11 +1965,23 @@ from_arbitrary_int_impl!(Int(i32), [i8, i16, i64, i128]); from_arbitrary_int_impl!(Int(i64), [i8, i16, i32, i128]); from_arbitrary_int_impl!(Int(i128), [i8, i32, i64, i16]); -from_native_impl!(Int(i8), [i8, i16, i32, i64, i128]); -from_native_impl!(Int(i16), [i8, i16, i32, i64, i128]); -from_native_impl!(Int(i32), [i8, i16, i32, i64, i128]); -from_native_impl!(Int(i64), [i8, i16, i32, i64, i128]); -from_native_impl!(Int(i128), [i8, i16, i32, i64, i128]); +from_native_smaller_impl!(Int(i8), [i16, i32, i64, i128]); +from_native_equal_impl!(Int(i8), [i8]); + +from_native_smaller_impl!(Int(i16), [i32, i64, i128]); +from_native_equal_impl!(Int(i16), [i16]); +from_native_bigger_impl!(Int(i16), [i8]); + +from_native_smaller_impl!(Int(i32), [i64, i128]); +from_native_equal_impl!(Int(i32), [i32]); +from_native_bigger_impl!(Int(i32), [i8, i16]); + +from_native_smaller_impl!(Int(i64), [i128]); +from_native_equal_impl!(Int(i64), [i64]); +from_native_bigger_impl!(Int(i64), [i8, i16, i32]); + +from_native_equal_impl!(Int(i128), [i128]); +from_native_bigger_impl!(Int(i128), [i8, i16, i32, i64]); use crate::common::{impl_borsh, impl_bytemuck_basic}; pub use aliases::*; diff --git a/src/unsigned.rs b/src/unsigned.rs index b16b3d3..f642bf3 100644 --- a/src/unsigned.rs +++ b/src/unsigned.rs @@ -1,10 +1,12 @@ use crate::common::{ - bytes_operation_impl, from_arbitrary_int_impl, from_native_impl, impl_bin_proto, impl_borsh, - impl_bytemuck_full, impl_extract, impl_num_traits, impl_schemars, impl_step, impl_sum_product, + bytes_operation_impl, from_arbitrary_int_impl, from_native_bigger_impl, from_native_equal_impl, + from_native_smaller_impl, impl_bin_proto, impl_borsh, impl_bytemuck_full, impl_extract, + impl_num_traits, impl_schemars, impl_step, impl_sum_product, }; use crate::traits::{sealed::Sealed, BuiltinInteger, Integer, UnsignedInteger}; use crate::TryNewError; use core::fmt::{Binary, Debug, Display, Formatter, LowerHex, Octal, UpperHex}; +use core::num::TryFromIntError; use core::ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Not, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, @@ -1687,11 +1689,64 @@ from_arbitrary_int_impl!(UInt(u32), [u8, u16, u64, u128]); from_arbitrary_int_impl!(UInt(u64), [u8, u16, u32, u128]); from_arbitrary_int_impl!(UInt(u128), [u8, u32, u64, u16]); -from_native_impl!(UInt(u8), [u8, u16, u32, u64, u128]); -from_native_impl!(UInt(u16), [u8, u16, u32, u64, u128]); -from_native_impl!(UInt(u32), [u8, u16, u32, u64, u128]); -from_native_impl!(UInt(u64), [u8, u16, u32, u64, u128]); -from_native_impl!(UInt(u128), [u8, u16, u32, u64, u128]); +from_native_smaller_impl!(UInt(u8), [u16, u32, u64, u128]); +from_native_equal_impl!(UInt(u8), [u8]); + +from_native_smaller_impl!(UInt(u16), [u32, u64, u128]); +from_native_equal_impl!(UInt(u16), [u16]); +from_native_bigger_impl!(UInt(u16), [u8]); + +from_native_smaller_impl!(UInt(u32), [u64, u128]); +from_native_equal_impl!(UInt(u32), [u32]); +from_native_bigger_impl!(UInt(u32), [u8, u16]); + +from_native_smaller_impl!(UInt(u64), [u128]); +from_native_equal_impl!(UInt(u64), [u64]); +from_native_bigger_impl!(UInt(u64), [u8, u16, u32]); + +from_native_equal_impl!(UInt(u128), [u128]); +from_native_bigger_impl!(UInt(u128), [u8, u16, u32, u64]); + +impl< + T: UnsignedInteger + BuiltinInteger + TryFrom, + const BITS: usize, + > TryFrom for UInt +where + Self: Integer, + ::UnderlyingType: TryFrom, +{ + type Error = TryFromIntError; + + fn try_from(value: usize) -> Result { + Ok(Self::new(value.try_into()?)) + } +} + +impl< + T: UnsignedInteger + BuiltinInteger + TryInto, + const BITS: usize, + > TryFrom> for usize +{ + type Error = TryFromIntError; + + fn try_from(value: UInt) -> Result { + value.value.try_into() + } +} +// impl< +// T: UnsignedInteger + BuiltinInteger + TryFrom, +// const BITS: usize, +// > TryFrom> for usize +// where +// UInt: Integer, +// ::UnderlyingType: TryFrom, +// { +// type Error = TryFromIntError; + +// fn try_from(value: usize) -> Result { +// Ok(Self::new(value.try_into()?)) +// } +// } pub use aliases::*;