Skip to content

Commit bb326f8

Browse files
committed
Let Int512::new take an i128 argument
1 parent 8ce31d1 commit bb326f8

File tree

2 files changed

+73
-21
lines changed

2 files changed

+73
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ and this project adheres to
4141
makes the use of `schemars` optional for contracts. ([#2201])
4242
- cosmwasm-std: Remove `schemars::JsonSchema` requirement from `CustomMsg`.
4343
([#2201])
44-
- cosmwasm-std: `Int256::new` now takes an `i128` argument instead of bytes. Use
45-
`Int256::from_be_bytes` if you need the old behaviour.
44+
- cosmwasm-std: `Int256::new`/`Int512::new` now take an `i128` argument instead
45+
of bytes. Use `::from_be_bytes` if you need the old behaviour.
4646

4747
## Fixed
4848

packages/std/src/math/int512.rs

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ use super::num_consts::NumConsts;
2626
///
2727
/// # Examples
2828
///
29-
/// Use `from` to create instances out of primitive uint types or `new` to provide big
30-
/// endian bytes:
29+
/// Use `new` to create instances out of i128, `from` for other primitive uint/int types
30+
/// or `from_be_bytes` to provide big endian bytes:
3131
///
3232
/// ```
3333
/// # use cosmwasm_std::Int512;
34-
/// let a = Int512::from(258u128);
35-
/// let b = Int512::new([
34+
/// let a = Int512::new(258i128);
35+
/// let b = Int512::from(258u128);
36+
/// let c = Int512::from_be_bytes([
3637
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
3738
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
3839
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
@@ -43,6 +44,7 @@ use super::num_consts::NumConsts;
4344
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
4445
/// ]);
4546
/// assert_eq!(a, b);
47+
/// assert_eq!(a, c);
4648
/// ```
4749
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
4850
pub struct Int512(#[schemars(with = "String")] pub(crate) I512);
@@ -54,11 +56,33 @@ impl Int512 {
5456
pub const MAX: Int512 = Int512(I512::MAX);
5557
pub const MIN: Int512 = Int512(I512::MIN);
5658

57-
/// Creates a Int512(value) from a big endian representation. It's just an alias for
58-
/// `from_be_bytes`.
59+
/// Creates a Int512(value).
60+
///
61+
/// This method is less flexible than `from` but can be called in a const context.
62+
///
63+
/// Before CosmWasm 3 this took a byte array as an argument. You can get this behaviour
64+
/// with [`from_be_bytes`].
65+
///
66+
/// [`from_be_bytes`]: Self::from_be_bytes
5967
#[inline]
60-
pub const fn new(value: [u8; 64]) -> Self {
61-
Self::from_be_bytes(value)
68+
pub const fn new(value: i128) -> Self {
69+
// See https://en.wikipedia.org/wiki/Sign_extension
70+
let b = value.to_be_bytes();
71+
if value.is_negative() {
72+
Self::from_be_bytes([
73+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
75+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
76+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
77+
b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15],
78+
])
79+
} else {
80+
Self::from_be_bytes([
81+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, b[0], b[1], b[2], b[3],
83+
b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15],
84+
])
85+
}
6286
}
6387

6488
/// Creates a Int512(0)
@@ -585,7 +609,37 @@ mod tests {
585609

586610
#[test]
587611
fn int512_new_works() {
588-
let num = Int512::new([1; 64]);
612+
let num = Int512::new(1);
613+
assert_eq!(
614+
num.to_be_bytes(),
615+
[
616+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
617+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
618+
0, 0, 0, 0, 0, 0, 0, 1
619+
]
620+
);
621+
622+
let num = Int512::new(-1);
623+
assert_eq!(
624+
num.to_be_bytes(),
625+
[
626+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
627+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
628+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
629+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
630+
]
631+
);
632+
633+
for v in [0, 1, -4, 18, 875786576, -11763498739, i128::MAX, i128::MIN] {
634+
// From is implemented by bnum, so we test two independent implementations against each other
635+
let uut = Int512::new(v);
636+
assert_eq!(uut, Int512::from(v));
637+
}
638+
}
639+
640+
#[test]
641+
fn int512_from_be_bytes_works() {
642+
let num = Int512::from_be_bytes([1; 64]);
589643
let a: [u8; 64] = num.to_be_bytes();
590644
assert_eq!(a, [1; 64]);
591645

@@ -595,14 +649,14 @@ mod tests {
595649
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
596650
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
597651
];
598-
let num = Int512::new(be_bytes);
652+
let num = Int512::from_be_bytes(be_bytes);
599653
let resulting_bytes: [u8; 64] = num.to_be_bytes();
600654
assert_eq!(be_bytes, resulting_bytes);
601655
}
602656

603657
#[test]
604658
fn int512_not_works() {
605-
let num = Int512::new([1; 64]);
659+
let num = Int512::from_be_bytes([1; 64]);
606660
let a = (!num).to_be_bytes();
607661
assert_eq!(a, [254; 64]);
608662

@@ -643,12 +697,10 @@ mod tests {
643697
];
644698

645699
// These should all be the same.
646-
let num1 = Int512::new(be_bytes);
647-
let num2 = Int512::from_be_bytes(be_bytes);
648-
let num3 = Int512::from_le_bytes(le_bytes);
649-
assert_eq!(num1, Int512::from(65536u32 + 512 + 3));
650-
assert_eq!(num1, num2);
651-
assert_eq!(num1, num3);
700+
let a = Int512::from_be_bytes(be_bytes);
701+
let b = Int512::from_le_bytes(le_bytes);
702+
assert_eq!(a, Int512::from(65536u32 + 512 + 3));
703+
assert_eq!(a, b);
652704
}
653705

654706
#[test]
@@ -1028,14 +1080,14 @@ mod tests {
10281080

10291081
#[test]
10301082
fn int512_shr_works() {
1031-
let original = Int512::new([
1083+
let original = Int512::from_be_bytes([
10321084
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
10331085
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
10341086
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
10351087
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
10361088
]);
10371089

1038-
let shifted = Int512::new([
1090+
let shifted = Int512::from_be_bytes([
10391091
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
10401092
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
10411093
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,

0 commit comments

Comments
 (0)