Add Arithmetic Shift Left operation for I256. Minor update to the ASR tests to include coverage for a shift of 0, and move to 'I256::minus_one' over 'I256::from(-1i8)' syntax (#1452)
Co-authored-by: Dave Belvedere <dave@protonmail.com>
This commit is contained in:
parent
7fac88a649
commit
5c9a048f73
|
@ -93,6 +93,7 @@
|
||||||
- [#1632](https://github.com/gakonst/ethers-rs/pull/1632) Re-export `H32` from `ethabi`.
|
- [#1632](https://github.com/gakonst/ethers-rs/pull/1632) Re-export `H32` from `ethabi`.
|
||||||
- [#1634](https://github.com/gakonst/ethers-rs/pull/1634) Derive missing `Clone`, `Copy` and `Debug` impls in ethers-etherscan.
|
- [#1634](https://github.com/gakonst/ethers-rs/pull/1634) Derive missing `Clone`, `Copy` and `Debug` impls in ethers-etherscan.
|
||||||
- Bytes debug format now displays hex literals [#1658](https://github.com/gakonst/ethers-rs/pull/1658)
|
- Bytes debug format now displays hex literals [#1658](https://github.com/gakonst/ethers-rs/pull/1658)
|
||||||
|
- [#1451](https://github.com/gakonst/ethers-rs/issues/1451) Add Arithemtic Shift Left operation for I256
|
||||||
|
|
||||||
## ethers-contract-abigen
|
## ethers-contract-abigen
|
||||||
|
|
||||||
|
|
|
@ -943,7 +943,7 @@ impl I256 {
|
||||||
// It's always going to be zero (i.e. 00000000...00000000)
|
// It's always going to be zero (i.e. 00000000...00000000)
|
||||||
Sign::Positive => Self::zero(),
|
Sign::Positive => Self::zero(),
|
||||||
// It's always going to be -1 (i.e. 11111111...11111111)
|
// It's always going to be -1 (i.e. 11111111...11111111)
|
||||||
Sign::Negative => Self::from(-1i8),
|
Sign::Negative => Self::minus_one(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Perform the shift.
|
// Perform the shift.
|
||||||
|
@ -960,6 +960,24 @@ impl I256 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Arithmetic Shift Left operation. Shifts `shift` number of times to the left, checking for
|
||||||
|
/// overflow on the final result.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the operation overflowed (most significant bit changes).
|
||||||
|
pub fn asl(self, shift: u32) -> Option<Self> {
|
||||||
|
if shift == 0 {
|
||||||
|
Some(self)
|
||||||
|
} else {
|
||||||
|
let result = self << shift;
|
||||||
|
if result.sign() != self.sign() {
|
||||||
|
// Overflow occured
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_from {
|
macro_rules! impl_from {
|
||||||
|
@ -1553,16 +1571,16 @@ mod tests {
|
||||||
let expected_result = I256::from_raw(U256::MAX.sub(1u8));
|
let expected_result = I256::from_raw(U256::MAX.sub(1u8));
|
||||||
assert_eq!(value.asr(253u32), expected_result, "1011...1111 >> 253 was not 1111...1110");
|
assert_eq!(value.asr(253u32), expected_result, "1011...1111 >> 253 was not 1111...1110");
|
||||||
|
|
||||||
let value = I256::from(-1i8);
|
let value = I256::minus_one();
|
||||||
let expected_result = I256::from(-1i8);
|
let expected_result = I256::minus_one();
|
||||||
assert_eq!(value.asr(250u32), expected_result, "-1 >> any_amount was not -1");
|
assert_eq!(value.asr(250u32), expected_result, "-1 >> any_amount was not -1");
|
||||||
|
|
||||||
let value = I256::from_raw(U256::from(2u8).pow(U256::from(254u8))).neg();
|
let value = I256::from_raw(U256::from(2u8).pow(U256::from(254u8))).neg();
|
||||||
let expected_result = I256::from(-1i8);
|
let expected_result = I256::minus_one();
|
||||||
assert_eq!(value.asr(255u32), expected_result, "1011...1111 >> 255 was not -1");
|
assert_eq!(value.asr(255u32), expected_result, "1011...1111 >> 255 was not -1");
|
||||||
|
|
||||||
let value = I256::from_raw(U256::from(2u8).pow(U256::from(254u8))).neg();
|
let value = I256::from_raw(U256::from(2u8).pow(U256::from(254u8))).neg();
|
||||||
let expected_result = I256::from(-1i8);
|
let expected_result = I256::minus_one();
|
||||||
assert_eq!(value.asr(1024u32), expected_result, "1011...1111 >> 1024 was not -1");
|
assert_eq!(value.asr(1024u32), expected_result, "1011...1111 >> 1024 was not -1");
|
||||||
|
|
||||||
let value = I256::from(1024i32);
|
let value = I256::from(1024i32);
|
||||||
|
@ -1572,6 +1590,49 @@ mod tests {
|
||||||
let value = I256::MAX;
|
let value = I256::MAX;
|
||||||
let expected_result = I256::zero();
|
let expected_result = I256::zero();
|
||||||
assert_eq!(value.asr(255u32), expected_result, "I256::MAX >> 255 was not 0");
|
assert_eq!(value.asr(255u32), expected_result, "I256::MAX >> 255 was not 0");
|
||||||
|
|
||||||
|
let value = I256::from_raw(U256::from(2u8).pow(U256::from(254u8))).neg();
|
||||||
|
let expected_result = value;
|
||||||
|
assert_eq!(value.asr(0u32), expected_result, "1011...1111 >> 0 was not 1011...111");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arithmetic_shift_left() {
|
||||||
|
let value = I256::minus_one();
|
||||||
|
let expected_result = Some(value);
|
||||||
|
assert_eq!(value.asl(0u32), expected_result, "-1 << 0 was not -1");
|
||||||
|
|
||||||
|
let value = I256::minus_one();
|
||||||
|
let expected_result = None;
|
||||||
|
assert_eq!(
|
||||||
|
value.asl(256u32),
|
||||||
|
expected_result,
|
||||||
|
"-1 << 256 did not overflow (result should be 0000...0000)"
|
||||||
|
);
|
||||||
|
|
||||||
|
let value = I256::minus_one();
|
||||||
|
let expected_result = Some(I256::from_raw(U256::from(2u8).pow(U256::from(255u8))));
|
||||||
|
assert_eq!(value.asl(255u32), expected_result, "-1 << 255 was not 1000...0000");
|
||||||
|
|
||||||
|
let value = I256::from(-1024i32);
|
||||||
|
let expected_result = Some(I256::from(-32768i32));
|
||||||
|
assert_eq!(value.asl(5u32), expected_result, "-1024 << 5 was not -32768");
|
||||||
|
|
||||||
|
let value = I256::from(1024i32);
|
||||||
|
let expected_result = Some(I256::from(32768i32));
|
||||||
|
assert_eq!(value.asl(5u32), expected_result, "1024 << 5 was not 32768");
|
||||||
|
|
||||||
|
let value = I256::from(1024i32);
|
||||||
|
let expected_result = None;
|
||||||
|
assert_eq!(
|
||||||
|
value.asl(245u32),
|
||||||
|
expected_result,
|
||||||
|
"1024 << 245 did not overflow (result should be 1000...0000)"
|
||||||
|
);
|
||||||
|
|
||||||
|
let value = I256::zero();
|
||||||
|
let expected_result = Some(value);
|
||||||
|
assert_eq!(value.asl(1024u32), expected_result, "0 << anything was not 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue