@@ -29,19 +29,21 @@ use super::num_consts::NumConsts;
29
29
///
30
30
/// # Examples
31
31
///
32
- /// Use `from ` to create instances out of primitive uint types or `new` to provide big
33
- /// endian bytes:
32
+ /// Use `new ` to create instances out of i128, `from` for other primitive uint/int types
33
+ /// or `from_be_bytes` to provide big endian bytes:
34
34
///
35
35
/// ```
36
36
/// # use cosmwasm_std::Int256;
37
- /// let a = Int256::from(258u128);
38
- /// let b = Int256::new([
37
+ /// let a = Int256::new(258i128);
38
+ /// let b = Int256::from(258u16);
39
+ /// let c = Int256::from_be_bytes([
39
40
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
40
41
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
41
42
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
42
43
/// 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
43
44
/// ]);
44
45
/// assert_eq!(a, b);
46
+ /// assert_eq!(a, c);
45
47
/// ```
46
48
#[ derive( Copy , Clone , Default , Debug , PartialEq , Eq , PartialOrd , Ord , schemars:: JsonSchema ) ]
47
49
pub struct Int256 ( #[ schemars( with = "String" ) ] pub ( crate ) I256 ) ;
@@ -53,11 +55,30 @@ impl Int256 {
53
55
pub const MAX : Int256 = Int256 ( I256 :: MAX ) ;
54
56
pub const MIN : Int256 = Int256 ( I256 :: MIN ) ;
55
57
56
- /// Creates a Int256(value) from a big endian representation. It's just an alias for
57
- /// `from_be_bytes`.
58
+ /// Creates a Int256(value).
59
+ ///
60
+ /// This method is less flexible than `from` but can be called in a const context.
61
+ ///
62
+ /// Before CosmWasm 3 this took a byte array as an argument. You can get this behaviour
63
+ /// with [`from_be_bytes`].
64
+ ///
65
+ /// [`from_be_bytes`]: Self::from_be_bytes
58
66
#[ inline]
59
- pub const fn new ( value : [ u8 ; 32 ] ) -> Self {
60
- Self :: from_be_bytes ( value)
67
+ pub const fn new ( value : i128 ) -> Self {
68
+ // See https://en.wikipedia.org/wiki/Sign_extension
69
+ let b = value. to_be_bytes ( ) ;
70
+ if value. is_negative ( ) {
71
+ Self :: from_be_bytes ( [
72
+ 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
73
+ 0xFF , 0xFF , b[ 0 ] , b[ 1 ] , b[ 2 ] , b[ 3 ] , b[ 4 ] , b[ 5 ] , b[ 6 ] , b[ 7 ] , b[ 8 ] , b[ 9 ] , b[ 10 ] ,
74
+ b[ 11 ] , b[ 12 ] , b[ 13 ] , b[ 14 ] , b[ 15 ] ,
75
+ ] )
76
+ } else {
77
+ Self :: from_be_bytes ( [
78
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , b[ 0 ] , b[ 1 ] , b[ 2 ] , b[ 3 ] , b[ 4 ] , b[ 5 ] ,
79
+ b[ 6 ] , b[ 7 ] , b[ 8 ] , b[ 9 ] , b[ 10 ] , b[ 11 ] , b[ 12 ] , b[ 13 ] , b[ 14 ] , b[ 15 ] ,
80
+ ] )
81
+ }
61
82
}
62
83
63
84
/// Creates a Int256(0)
@@ -588,22 +609,49 @@ mod tests {
588
609
589
610
#[ test]
590
611
fn int256_new_works ( ) {
591
- let num = Int256 :: new ( [ 1 ; 32 ] ) ;
612
+ let num = Int256 :: 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 , 1
618
+ ]
619
+ ) ;
620
+
621
+ let num = Int256 :: new ( -1 ) ;
622
+ assert_eq ! (
623
+ num. to_be_bytes( ) ,
624
+ [
625
+ 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 ,
626
+ 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 ,
627
+ ]
628
+ ) ;
629
+
630
+ for v in [ 0 , 1 , -4 , 18 , 875786576 , -11763498739 , i128:: MAX , i128:: MIN ] {
631
+ // From is implemented by bnum, so we test two independent implementations against each other
632
+ let uut = Int256 :: new ( v) ;
633
+ assert_eq ! ( uut, Int256 :: from( v) ) ;
634
+ }
635
+ }
636
+
637
+ #[ test]
638
+ fn int256_from_be_bytes_works ( ) {
639
+ let num = Int256 :: from_be_bytes ( [ 1 ; 32 ] ) ;
592
640
let a: [ u8 ; 32 ] = num. to_be_bytes ( ) ;
593
641
assert_eq ! ( a, [ 1 ; 32 ] ) ;
594
642
595
643
let be_bytes = [
596
644
0u8 , 222u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 ,
597
645
0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 1u8 , 2u8 , 3u8 ,
598
646
] ;
599
- let num = Int256 :: new ( be_bytes) ;
647
+ let num = Int256 :: from_be_bytes ( be_bytes) ;
600
648
let resulting_bytes: [ u8 ; 32 ] = num. to_be_bytes ( ) ;
601
649
assert_eq ! ( be_bytes, resulting_bytes) ;
602
650
}
603
651
604
652
#[ test]
605
653
fn int256_not_works ( ) {
606
- let num = Int256 :: new ( [ 1 ; 32 ] ) ;
654
+ let num = Int256 :: from_be_bytes ( [ 1 ; 32 ] ) ;
607
655
let a = ( !num) . to_be_bytes ( ) ;
608
656
assert_eq ! ( a, [ 254 ; 32 ] ) ;
609
657
@@ -640,12 +688,10 @@ mod tests {
640
688
] ;
641
689
642
690
// These should all be the same.
643
- let num1 = Int256 :: new ( be_bytes) ;
644
- let num2 = Int256 :: from_be_bytes ( be_bytes) ;
645
- let num3 = Int256 :: from_le_bytes ( le_bytes) ;
646
- assert_eq ! ( num1, Int256 :: from( 65536u32 + 512 + 3 ) ) ;
647
- assert_eq ! ( num1, num2) ;
648
- assert_eq ! ( num1, num3) ;
691
+ let a = Int256 :: from_be_bytes ( be_bytes) ;
692
+ let b = Int256 :: from_le_bytes ( le_bytes) ;
693
+ assert_eq ! ( a, Int256 :: from( 65536u32 + 512 + 3 ) ) ;
694
+ assert_eq ! ( a, b) ;
649
695
}
650
696
651
697
#[ test]
@@ -1059,12 +1105,12 @@ mod tests {
1059
1105
1060
1106
#[ test]
1061
1107
fn int256_shr_works ( ) {
1062
- let original = Int256 :: new ( [
1108
+ let original = Int256 :: from_be_bytes ( [
1063
1109
0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 ,
1064
1110
0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 2u8 , 0u8 , 4u8 , 2u8 ,
1065
1111
] ) ;
1066
1112
1067
- let shifted = Int256 :: new ( [
1113
+ let shifted = Int256 :: from_be_bytes ( [
1068
1114
0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 ,
1069
1115
0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 128u8 , 1u8 , 0u8 ,
1070
1116
] ) ;
0 commit comments