Skip to content

Use newly added panicking_add/panicking_sub for Timestamp math (backport #2098) #2105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 10, 2024
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ and this project adheres to
- cosmwasm-std: Implement `&T + T` and `&T op &T` for `Uint64`, `Uint128`,
`Uint256` and `Uint512`; improve panic message for `Uint64::add` and
`Uint512::add` ([#2092])
- cosmwasm-std: Add `Uint{64,128,256,512}::panicking_add` and `::panicking_sub`
which are like the `Add`/`Sub` implementations but `const`. ([#2098])
- cosmwasm-std: Let `Timestamp::plus_nanos`/`::minus_nanos` use
`Uint64::panicking_add`/`::panicking_sub` and document overflows. ([#2098])

[#2092]: https://github.com/CosmWasm/cosmwasm/pull/2092
[#2098]: https://github.com/CosmWasm/cosmwasm/pull/2098

### Changed

Expand Down
49 changes: 39 additions & 10 deletions packages/std/src/math/uint128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,28 @@ impl Uint128 {
Self(self.0.saturating_pow(exp))
}

/// This is the same as [`Uint128::add`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_add(self, other: Self) -> Self {
match self.0.checked_add(other.u128()) {
None => panic!("attempt to add with overflow"),
Some(sum) => Self(sum),
}
}

/// This is the same as [`Uint128::sub`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_sub(self, other: Self) -> Self {
match self.0.checked_sub(other.u128()) {
None => panic!("attempt to subtract with overflow"),
Some(diff) => Self(diff),
}
}

#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn abs_diff(self, other: Self) -> Self {
Self(if self.0 < other.0 {
Expand Down Expand Up @@ -363,11 +385,7 @@ impl Add<Uint128> for Uint128 {
type Output = Self;

fn add(self, rhs: Self) -> Self {
Self(
self.u128()
.checked_add(rhs.u128())
.expect("attempt to add with overflow"),
)
self.panicking_add(rhs)
}
}
forward_ref_binop!(impl Add, add for Uint128, Uint128);
Expand All @@ -376,11 +394,7 @@ impl Sub<Uint128> for Uint128 {
type Output = Self;

fn sub(self, rhs: Self) -> Self {
Uint128(
self.u128()
.checked_sub(rhs.u128())
.expect("attempt to subtract with overflow"),
)
self.panicking_sub(rhs)
}
}
forward_ref_binop!(impl Sub, sub for Uint128, Uint128);
Expand Down Expand Up @@ -1148,6 +1162,21 @@ mod tests {
assert_eq!(a, Uint128::from(1u32));
}

#[test]
fn uint128_panicking_sub_works() {
let a = Uint128::new(5);
let b = Uint128::new(3);
assert_eq!(a.panicking_sub(b), Uint128::new(2));
}

#[test]
#[should_panic(expected = "attempt to subtract with overflow")]
fn uint128_panicking_sub_panics_on_overflow() {
let a = Uint128::zero();
let b = Uint128::one();
let _diff = a.panicking_sub(b);
}

#[test]
fn uint128_abs_diff_works() {
let a = Uint128::from(42u32);
Expand Down
49 changes: 39 additions & 10 deletions packages/std/src/math/uint256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,28 @@ impl Uint256 {
Self(self.0.saturating_pow(exp))
}

/// This is the same as [`Uint256::add`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_add(self, other: Self) -> Self {
match self.0.checked_add(other.0) {
None => panic!("attempt to add with overflow"),
Some(sum) => Self(sum),
}
}

/// This is the same as [`Uint256::sub`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_sub(self, other: Self) -> Self {
match self.0.checked_sub(other.0) {
None => panic!("attempt to subtract with overflow"),
Some(diff) => Self(diff),
}
}

#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn abs_diff(self, other: Self) -> Self {
Self(self.0.abs_diff(other.0))
Expand Down Expand Up @@ -428,11 +450,7 @@ impl Add<Uint256> for Uint256 {
type Output = Self;

fn add(self, rhs: Self) -> Self {
Self(
self.0
.checked_add(rhs.0)
.expect("attempt to add with overflow"),
)
self.panicking_add(rhs)
}
}
forward_ref_binop!(impl Add, add for Uint256, Uint256);
Expand All @@ -441,11 +459,7 @@ impl Sub<Uint256> for Uint256 {
type Output = Self;

fn sub(self, rhs: Self) -> Self {
Self(
self.0
.checked_sub(rhs.0)
.expect("attempt to subtract with overflow"),
)
self.panicking_sub(rhs)
}
}
forward_ref_binop!(impl Sub, sub for Uint256, Uint256);
Expand Down Expand Up @@ -1690,6 +1704,21 @@ mod tests {
assert_eq!(a, Uint256::from(1u32));
}

#[test]
fn uint256_panicking_sub_works() {
let a = Uint256::from(5u32);
let b = Uint256::from(3u32);
assert_eq!(a.panicking_sub(b), Uint256::from(2u32));
}

#[test]
#[should_panic(expected = "attempt to subtract with overflow")]
fn uint256_panicking_sub_panics_on_overflow() {
let a = Uint256::zero();
let b = Uint256::one();
let _diff = a.panicking_sub(b);
}

#[test]
fn uint256_abs_diff_works() {
let a = Uint256::from(42u32);
Expand Down
45 changes: 39 additions & 6 deletions packages/std/src/math/uint512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,28 @@ impl Uint512 {
Self(self.0.saturating_pow(exp))
}

/// This is the same as [`Uint512::add`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_add(self, other: Self) -> Self {
match self.0.checked_add(other.0) {
None => panic!("attempt to add with overflow"),
Some(sum) => Self(sum),
}
}

/// This is the same as [`Uint512::sub`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_sub(self, other: Self) -> Self {
match self.0.checked_sub(other.0) {
None => panic!("attempt to subtract with overflow"),
Some(diff) => Self(diff),
}
}

#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn abs_diff(self, other: Self) -> Self {
Self(self.0.abs_diff(other.0))
Expand Down Expand Up @@ -415,11 +437,7 @@ impl Add<Uint512> for Uint512 {
type Output = Self;

fn add(self, rhs: Self) -> Self {
Self(
self.0
.checked_add(rhs.0)
.expect("attempt to add with overflow"),
)
self.panicking_add(rhs)
}
}
forward_ref_binop!(impl Add, add for Uint512, Uint512);
Expand All @@ -428,7 +446,7 @@ impl Sub<Uint512> for Uint512 {
type Output = Self;

fn sub(self, rhs: Self) -> Self {
Uint512(self.0.checked_sub(rhs.0).unwrap())
self.panicking_sub(rhs)
}
}
forward_ref_binop!(impl Sub, sub for Uint512, Uint512);
Expand Down Expand Up @@ -1338,6 +1356,21 @@ mod tests {
assert_eq!(a, Uint512::from(1u32));
}

#[test]
fn uint512_panicking_sub_works() {
let a = Uint512::from(5u32);
let b = Uint512::from(3u32);
assert_eq!(a.panicking_sub(b), Uint512::from(2u32));
}

#[test]
#[should_panic(expected = "attempt to subtract with overflow")]
fn uint512_panicking_sub_panics_on_overflow() {
let a = Uint512::zero();
let b = Uint512::one();
let _diff = a.panicking_sub(b);
}

#[test]
fn uint512_abs_diff_works() {
let a = Uint512::from(42u32);
Expand Down
49 changes: 39 additions & 10 deletions packages/std/src/math/uint64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,28 @@ impl Uint64 {
Self(self.0.saturating_pow(exp))
}

/// This is the same as [`Uint64::add`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_add(self, other: Self) -> Self {
match self.0.checked_add(other.u64()) {
None => panic!("attempt to add with overflow"),
Some(sum) => Self(sum),
}
}

/// This is the same as [`Uint64::sub`] but const.
///
/// Panics on overflow.
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn panicking_sub(self, other: Self) -> Self {
match self.0.checked_sub(other.u64()) {
None => panic!("attempt to subtract with overflow"),
Some(diff) => Self(diff),
}
}

#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn abs_diff(self, other: Self) -> Self {
Self(if self.0 < other.0 {
Expand Down Expand Up @@ -326,11 +348,7 @@ impl Add<Uint64> for Uint64 {
type Output = Self;

fn add(self, rhs: Self) -> Self {
Self(
self.u64()
.checked_add(rhs.u64())
.expect("attempt to add with overflow"),
)
self.panicking_add(rhs)
}
}
forward_ref_binop!(impl Add, add for Uint64, Uint64);
Expand All @@ -339,11 +357,7 @@ impl Sub<Uint64> for Uint64 {
type Output = Self;

fn sub(self, rhs: Self) -> Self {
Uint64(
self.u64()
.checked_sub(rhs.u64())
.expect("attempt to subtract with overflow"),
)
self.panicking_sub(rhs)
}
}
forward_ref_binop!(impl Sub, sub for Uint64, Uint64);
Expand Down Expand Up @@ -1062,6 +1076,21 @@ mod tests {
assert_eq!(a, Uint64::from(1u32));
}

#[test]
fn uint64_panicking_sub_works() {
let a = Uint64::new(5);
let b = Uint64::new(3);
assert_eq!(a.panicking_sub(b), Uint64::new(2));
}

#[test]
#[should_panic(expected = "attempt to subtract with overflow")]
fn uint64_panicking_sub_panics_on_overflow() {
let a = Uint64::zero();
let b = Uint64::one();
let _diff = a.panicking_sub(b);
}

#[test]
fn uint64_abs_diff_works() {
let a = Uint64::from(42u32);
Expand Down
Loading
Loading