diff --git a/CHANGELOG.md b/CHANGELOG.md index cadd35424..d1c171c93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ and this project adheres to ## [Unreleased] +## Added + +- cosmwasm-std: Implement `From for u{64,128}`, + `From for u128`, `From for i{64,128}`, and + `From for i128` ([#2268]) + +[#2268]: https://github.com/CosmWasm/cosmwasm/issues/2268 + ## [2.2.0] - 2024-12-17 ### Added diff --git a/packages/std/src/math/conversion.rs b/packages/std/src/math/conversion.rs index 8b31b8461..0f05a7013 100644 --- a/packages/std/src/math/conversion.rs +++ b/packages/std/src/math/conversion.rs @@ -82,6 +82,34 @@ macro_rules! forward_try_from { } pub(crate) use forward_try_from; +/// Helper macro to implement `From` for a type that is just a wrapper around another type. +/// This can be used for all our integer conversions where `bnum` implements `From`. +macro_rules! wrapped_int_to_primitive { + ($input: ty, $output: ty) => { + impl From<$input> for $output { + fn from(value: $input) -> Self { + // By convention all our Uint*/Int* types store the value in .0 + value.0.into() + } + } + }; +} +pub(crate) use wrapped_int_to_primitive; + +/// Helper macro to implement `From` for a type that is just a wrapper around another type. +/// This can be used for all our integer conversions where `bnum` implements `From`. +macro_rules! primitive_to_wrapped_int { + ($input: ty, $output: ty) => { + impl From<$input> for $output { + fn from(value: $input) -> Self { + // By convention all our Uint*/Int* types store the value in .0 + Self(value.into()) + } + } + }; +} +pub(crate) use primitive_to_wrapped_int; + /// Helper macro to implement `TryFrom` for a conversion from a bigger signed int to a smaller one. /// This is needed because `bnum` does not implement `TryFrom` for those conversions /// because of limitations of const generics. diff --git a/packages/std/src/math/int128.rs b/packages/std/src/math/int128.rs index 9f0f35d59..9d8a060ab 100644 --- a/packages/std/src/math/int128.rs +++ b/packages/std/src/math/int128.rs @@ -13,7 +13,9 @@ use crate::{ __internal::forward_ref_partial_eq, }; -use super::conversion::{forward_try_from, try_from_int_to_int}; +use super::conversion::{ + forward_try_from, primitive_to_wrapped_int, try_from_int_to_int, wrapped_int_to_primitive, +}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -306,29 +308,10 @@ forward_try_from!(Uint256, Int128); forward_try_from!(Uint512, Int128); // uint to Int -impl From for Int128 { - fn from(val: u64) -> Self { - Int128(val.into()) - } -} - -impl From for Int128 { - fn from(val: u32) -> Self { - Int128(val.into()) - } -} - -impl From for Int128 { - fn from(val: u16) -> Self { - Int128(val.into()) - } -} - -impl From for Int128 { - fn from(val: u8) -> Self { - Int128(val.into()) - } -} +primitive_to_wrapped_int!(u8, Int128); +primitive_to_wrapped_int!(u16, Int128); +primitive_to_wrapped_int!(u32, Int128); +primitive_to_wrapped_int!(u64, Int128); // Int to Int impl From for Int128 { @@ -341,35 +324,14 @@ try_from_int_to_int!(Int256, Int128); try_from_int_to_int!(Int512, Int128); // int to Int -impl From for Int128 { - fn from(val: i128) -> Self { - Int128(val) - } -} +primitive_to_wrapped_int!(i8, Int128); +primitive_to_wrapped_int!(i16, Int128); +primitive_to_wrapped_int!(i32, Int128); +primitive_to_wrapped_int!(i64, Int128); +primitive_to_wrapped_int!(i128, Int128); -impl From for Int128 { - fn from(val: i64) -> Self { - Int128(val.into()) - } -} - -impl From for Int128 { - fn from(val: i32) -> Self { - Int128(val.into()) - } -} - -impl From for Int128 { - fn from(val: i16) -> Self { - Int128(val.into()) - } -} - -impl From for Int128 { - fn from(val: i8) -> Self { - Int128(val.into()) - } -} +// Int to int +wrapped_int_to_primitive!(Int128, i128); impl TryFrom<&str> for Int128 { type Error = StdError; @@ -626,6 +588,12 @@ mod tests { assert_eq!(num1, num2); } + #[test] + fn int128_convert_to() { + let a = Int128::new(5); + assert_eq!(i128::from(a), 5); + } + #[test] fn int128_convert_from() { let a = Int128::from(5i128); diff --git a/packages/std/src/math/int256.rs b/packages/std/src/math/int256.rs index e12b1d031..e0d4f19e7 100644 --- a/packages/std/src/math/int256.rs +++ b/packages/std/src/math/int256.rs @@ -17,7 +17,9 @@ use crate::{ /// the implementation in the future. use bnum::types::{I256, U256}; -use super::conversion::{grow_be_int, try_from_int_to_int, try_from_uint_to_int}; +use super::conversion::{ + grow_be_int, primitive_to_wrapped_int, try_from_int_to_int, try_from_uint_to_int, +}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -370,35 +372,11 @@ impl From for Int256 { } // uint to Int -impl From for Int256 { - fn from(val: u128) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: u64) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: u32) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: u16) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: u8) -> Self { - Int256(val.into()) - } -} +primitive_to_wrapped_int!(u8, Int256); +primitive_to_wrapped_int!(u16, Int256); +primitive_to_wrapped_int!(u32, Int256); +primitive_to_wrapped_int!(u64, Int256); +primitive_to_wrapped_int!(u128, Int256); // Int to Int try_from_int_to_int!(Int512, Int256); @@ -416,35 +394,11 @@ impl From for Int256 { } // int to Int -impl From for Int256 { - fn from(val: i128) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: i64) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: i32) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: i16) -> Self { - Int256(val.into()) - } -} - -impl From for Int256 { - fn from(val: i8) -> Self { - Int256(val.into()) - } -} +primitive_to_wrapped_int!(i8, Int256); +primitive_to_wrapped_int!(i16, Int256); +primitive_to_wrapped_int!(i32, Int256); +primitive_to_wrapped_int!(i64, Int256); +primitive_to_wrapped_int!(i128, Int256); impl TryFrom<&str> for Int256 { type Error = StdError; diff --git a/packages/std/src/math/int512.rs b/packages/std/src/math/int512.rs index c51351ae7..7b512b382 100644 --- a/packages/std/src/math/int512.rs +++ b/packages/std/src/math/int512.rs @@ -16,7 +16,7 @@ use crate::{ /// the implementation in the future. use bnum::types::{I512, U512}; -use super::conversion::{grow_be_int, try_from_uint_to_int}; +use super::conversion::{grow_be_int, primitive_to_wrapped_int, try_from_uint_to_int}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -365,66 +365,18 @@ impl From for Int512 { } // uint to Int -impl From for Int512 { - fn from(val: u128) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: u64) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: u32) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: u16) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: u8) -> Self { - Int512(val.into()) - } -} +primitive_to_wrapped_int!(u8, Int512); +primitive_to_wrapped_int!(u16, Int512); +primitive_to_wrapped_int!(u32, Int512); +primitive_to_wrapped_int!(u64, Int512); +primitive_to_wrapped_int!(u128, Int512); // int to Int -impl From for Int512 { - fn from(val: i128) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: i64) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: i32) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: i16) -> Self { - Int512(val.into()) - } -} - -impl From for Int512 { - fn from(val: i8) -> Self { - Int512(val.into()) - } -} +primitive_to_wrapped_int!(i8, Int512); +primitive_to_wrapped_int!(i16, Int512); +primitive_to_wrapped_int!(i32, Int512); +primitive_to_wrapped_int!(i64, Int512); +primitive_to_wrapped_int!(i128, Int512); // Int to Int impl From for Int512 { diff --git a/packages/std/src/math/int64.rs b/packages/std/src/math/int64.rs index 3a3594fe4..42777cb1a 100644 --- a/packages/std/src/math/int64.rs +++ b/packages/std/src/math/int64.rs @@ -13,7 +13,9 @@ use crate::{ __internal::forward_ref_partial_eq, }; -use super::conversion::{forward_try_from, try_from_int_to_int}; +use super::conversion::{ + forward_try_from, primitive_to_wrapped_int, try_from_int_to_int, wrapped_int_to_primitive, +}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -296,48 +298,19 @@ impl NumConsts for Int64 { } // uint to Int -impl From for Int64 { - fn from(val: u32) -> Self { - Int64(val.into()) - } -} - -impl From for Int64 { - fn from(val: u16) -> Self { - Int64(val.into()) - } -} - -impl From for Int64 { - fn from(val: u8) -> Self { - Int64(val.into()) - } -} +primitive_to_wrapped_int!(u8, Int64); +primitive_to_wrapped_int!(u16, Int64); +primitive_to_wrapped_int!(u32, Int64); // int to Int -impl From for Int64 { - fn from(val: i64) -> Self { - Int64(val) - } -} +primitive_to_wrapped_int!(i8, Int64); +primitive_to_wrapped_int!(i16, Int64); +primitive_to_wrapped_int!(i32, Int64); +primitive_to_wrapped_int!(i64, Int64); -impl From for Int64 { - fn from(val: i32) -> Self { - Int64(val.into()) - } -} - -impl From for Int64 { - fn from(val: i16) -> Self { - Int64(val.into()) - } -} - -impl From for Int64 { - fn from(val: i8) -> Self { - Int64(val.into()) - } -} +// Int to int +wrapped_int_to_primitive!(Int64, i64); +wrapped_int_to_primitive!(Int64, i128); // Int to Int try_from_int_to_int!(Int128, Int64); @@ -599,6 +572,15 @@ mod tests { assert_eq!(num1, num2); } + #[test] + fn int64_convert_to() { + let a = Int64::new(5); + assert_eq!(i64::from(a), 5); + + let a = Int64::new(5); + assert_eq!(i128::from(a), 5); + } + #[test] fn int64_convert_from() { let a = Int64::from(5i64); diff --git a/packages/std/src/math/uint128.rs b/packages/std/src/math/uint128.rs index 1511deca7..b82f4e491 100644 --- a/packages/std/src/math/uint128.rs +++ b/packages/std/src/math/uint128.rs @@ -16,7 +16,7 @@ use crate::{ Uint256, Uint64, }; -use super::conversion::forward_try_from; +use super::conversion::{forward_try_from, primitive_to_wrapped_int, wrapped_int_to_primitive}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -321,42 +321,22 @@ impl_mul_fraction!(Uint128); // of the conflict with `TryFrom<&str>` as described here // https://stackoverflow.com/questions/63136970/how-do-i-work-around-the-upstream-crates-may-add-a-new-impl-of-trait-error +// uint to Uint +primitive_to_wrapped_int!(u8, Uint128); +primitive_to_wrapped_int!(u16, Uint128); +primitive_to_wrapped_int!(u32, Uint128); +primitive_to_wrapped_int!(u64, Uint128); +primitive_to_wrapped_int!(u128, Uint128); + +// Uint to uint +wrapped_int_to_primitive!(Uint128, u128); + impl From for Uint128 { fn from(val: Uint64) -> Self { val.u64().into() } } -impl From for Uint128 { - fn from(val: u128) -> Self { - Uint128(val) - } -} - -impl From for Uint128 { - fn from(val: u64) -> Self { - Uint128(val.into()) - } -} - -impl From for Uint128 { - fn from(val: u32) -> Self { - Uint128(val.into()) - } -} - -impl From for Uint128 { - fn from(val: u16) -> Self { - Uint128(val.into()) - } -} - -impl From for Uint128 { - fn from(val: u8) -> Self { - Uint128(val.into()) - } -} - forward_try_from!(Uint128, Uint64); // Int to Uint @@ -390,12 +370,6 @@ impl From for String { } } -impl From for u128 { - fn from(original: Uint128) -> Self { - original.0 - } -} - impl fmt::Display for Uint128 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) diff --git a/packages/std/src/math/uint256.rs b/packages/std/src/math/uint256.rs index 88d310871..1f41327a7 100644 --- a/packages/std/src/math/uint256.rs +++ b/packages/std/src/math/uint256.rs @@ -20,7 +20,7 @@ use crate::{ /// the implementation in the future. use bnum::types::U256; -use super::conversion::{forward_try_from, try_from_int_to_uint}; +use super::conversion::{forward_try_from, primitive_to_wrapped_int, try_from_int_to_uint}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -385,6 +385,13 @@ impl NumConsts for Uint256 { impl_mul_fraction!(Uint256); +// uint to Uint +primitive_to_wrapped_int!(u8, Uint256); +primitive_to_wrapped_int!(u16, Uint256); +primitive_to_wrapped_int!(u32, Uint256); +primitive_to_wrapped_int!(u64, Uint256); +primitive_to_wrapped_int!(u128, Uint256); + impl From for Uint256 { fn from(val: Uint128) -> Self { val.u128().into() @@ -397,36 +404,6 @@ impl From for Uint256 { } } -impl From for Uint256 { - fn from(val: u128) -> Self { - Uint256(val.into()) - } -} - -impl From for Uint256 { - fn from(val: u64) -> Self { - Uint256(val.into()) - } -} - -impl From for Uint256 { - fn from(val: u32) -> Self { - Uint256(val.into()) - } -} - -impl From for Uint256 { - fn from(val: u16) -> Self { - Uint256(val.into()) - } -} - -impl From for Uint256 { - fn from(val: u8) -> Self { - Uint256(val.into()) - } -} - forward_try_from!(Uint256, Uint128); forward_try_from!(Uint256, Uint64); diff --git a/packages/std/src/math/uint512.rs b/packages/std/src/math/uint512.rs index 0332808df..834e9097a 100644 --- a/packages/std/src/math/uint512.rs +++ b/packages/std/src/math/uint512.rs @@ -18,7 +18,7 @@ use crate::{ /// the implementation in the future. use bnum::types::U512; -use super::conversion::{forward_try_from, try_from_int_to_uint}; +use super::conversion::{forward_try_from, primitive_to_wrapped_int, try_from_int_to_uint}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -348,6 +348,13 @@ impl NumConsts for Uint512 { const MIN: Self = Self::MIN; } +// uint to Uint +primitive_to_wrapped_int!(u8, Uint512); +primitive_to_wrapped_int!(u16, Uint512); +primitive_to_wrapped_int!(u32, Uint512); +primitive_to_wrapped_int!(u64, Uint512); +primitive_to_wrapped_int!(u128, Uint512); + impl From for Uint512 { fn from(val: Uint256) -> Self { let mut bytes = [0u8; 64]; @@ -369,36 +376,6 @@ impl From for Uint512 { } } -impl From for Uint512 { - fn from(val: u128) -> Self { - Uint512(val.into()) - } -} - -impl From for Uint512 { - fn from(val: u64) -> Self { - Uint512(val.into()) - } -} - -impl From for Uint512 { - fn from(val: u32) -> Self { - Uint512(val.into()) - } -} - -impl From for Uint512 { - fn from(val: u16) -> Self { - Uint512(val.into()) - } -} - -impl From for Uint512 { - fn from(val: u8) -> Self { - Uint512(val.into()) - } -} - impl TryFrom for Uint256 { type Error = ConversionOverflowError; diff --git a/packages/std/src/math/uint64.rs b/packages/std/src/math/uint64.rs index 9fecc2495..3e2aec182 100644 --- a/packages/std/src/math/uint64.rs +++ b/packages/std/src/math/uint64.rs @@ -15,7 +15,7 @@ use crate::{ Uint128, }; -use super::conversion::forward_try_from; +use super::conversion::{forward_try_from, primitive_to_wrapped_int, wrapped_int_to_primitive}; use super::impl_int_serde; use super::num_consts::NumConsts; @@ -318,29 +318,14 @@ impl_mul_fraction!(Uint64); // https://stackoverflow.com/questions/63136970/how-do-i-work-around-the-upstream-crates-may-add-a-new-impl-of-trait-error // uint to Uint -impl From for Uint64 { - fn from(val: u64) -> Self { - Uint64(val) - } -} +primitive_to_wrapped_int!(u8, Uint64); +primitive_to_wrapped_int!(u16, Uint64); +primitive_to_wrapped_int!(u32, Uint64); +primitive_to_wrapped_int!(u64, Uint64); -impl From for Uint64 { - fn from(val: u32) -> Self { - Uint64(val.into()) - } -} - -impl From for Uint64 { - fn from(val: u16) -> Self { - Uint64(val.into()) - } -} - -impl From for Uint64 { - fn from(val: u8) -> Self { - Uint64(val.into()) - } -} +// Uint to uint +wrapped_int_to_primitive!(Uint64, u64); +wrapped_int_to_primitive!(Uint64, u128); // Int to Uint forward_try_from!(Int64, Uint64); @@ -365,12 +350,6 @@ impl From for String { } } -impl From for u64 { - fn from(original: Uint64) -> Self { - original.0 - } -} - impl fmt::Display for Uint64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) @@ -599,6 +578,10 @@ mod tests { let a = u64::from(original); assert_eq!(a, 12345); + let original = Uint64(12345); + let a = u128::from(original); + assert_eq!(a, 12345); + let original = Uint64(12345); let a = String::from(original); assert_eq!(a, "12345");