Skip to content

Commit

Permalink
BigInt to u128 (#296)
Browse files Browse the repository at this point in the history
* BigInt to u128.

* Fmt.

* Fix clippy warnings.
  • Loading branch information
oskin1 authored Jan 29, 2024
1 parent 6df7876 commit 6e37d57
Showing 1 changed file with 45 additions and 2 deletions.
47 changes: 45 additions & 2 deletions chain/rust/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,28 @@ impl BigInteger {
}
}

/// Converts to a u128
/// Returns None if the number was negative or too big for a u128
pub fn as_u128(&self) -> Option<u128> {
let (sign, u32_digits) = self.num.to_u32_digits();
if sign == num_bigint::Sign::Minus {
return None;
}
match *u32_digits {
[] => Some(0),
[a] => Some(u128::from(a)),
[a, b] => Some(u128::from(b) | (u128::from(a) << 32)),
[a, b, c] => Some(u128::from(c) | (u128::from(b) << 32) | (u128::from(a) << 64)),
[a, b, c, d] => Some(
u128::from(d)
| (u128::from(c) << 32)
| (u128::from(b) << 64)
| (u128::from(a) << 96),
),
_ => None,
}
}

/// Converts to an Int
/// Returns None when the number is too big for an Int (outside +/- 64-bit unsigned)
/// Retains encoding info if the original was encoded as an Int
Expand Down Expand Up @@ -549,9 +571,10 @@ impl Deserialize for NetworkId {
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;

#[test]
fn bigint_uint_min() {
fn bigint_uint_u64_min() {
let bytes = [0x00];
let x = BigInteger::from_cbor_bytes(&bytes).unwrap();
assert_eq!(bytes, x.to_cbor_bytes().as_slice());
Expand All @@ -561,7 +584,7 @@ mod tests {
}

#[test]
fn bigint_uint_max() {
fn bigint_uint_u64_max() {
let bytes = [0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
let x = BigInteger::from_cbor_bytes(&bytes).unwrap();
assert_eq!(bytes, x.to_cbor_bytes().as_slice());
Expand All @@ -570,6 +593,26 @@ mod tests {
assert_eq!(x.to_string(), "18446744073709551615");
}

#[test]
fn bigint_uint_u128_min() {
let bytes = [0x00];
let x = BigInt::from_cbor_bytes(&bytes).unwrap();
assert_eq!(bytes, x.to_cbor_bytes().as_slice());
assert_eq!(x.as_u128(), Some(u128::MIN));
assert_eq!(x.to_string(), "0");
}

#[test]
fn bigint_uint_u128_max() {
let bytes = BigInt::from_str(&u128::MAX.to_string())
.unwrap()
.to_cbor_bytes();
let x = BigInt::from_cbor_bytes(&bytes).unwrap();
assert_eq!(bytes, x.to_cbor_bytes().as_slice());
assert_eq!(x.as_u128(), Some(u128::MAX));
assert_eq!(x.to_string(), "340282366920938463463374607431768211455");
}

#[test]
fn bigint_above_uint_min() {
let bytes = [
Expand Down

0 comments on commit 6e37d57

Please sign in to comment.