use core::str::FromStr;
use num_bigint::BigUint;
pub fn dec_to_biguint(s: &str) -> BigUint {
BigUint::from_str(s).unwrap_or_else(|_| panic!("invalid decimal integer: {s:?}"))
}
pub fn from_hex(s: &str) -> Vec<u8> {
let bytes = s.as_bytes();
let mut out = Vec::with_capacity(bytes.len() / 2);
let mut i = 0;
while i + 1 < bytes.len() {
match (hex_nibble(bytes[i]), hex_nibble(bytes[i + 1])) {
(Some(hi), Some(lo)) => {
out.push((hi << 4) | lo);
i += 2;
}
_ => break, }
}
out
}
fn hex_nibble(b: u8) -> Option<u8> {
match b {
b'0'..=b'9' => Some(b - b'0'),
b'a'..=b'f' => Some(b - b'a' + 10),
b'A'..=b'F' => Some(b - b'A' + 10),
_ => None,
}
}
pub fn le_bytes_to_biguint(bytes: &[u8]) -> BigUint {
BigUint::from_bytes_le(bytes)
}
pub fn biguint_to_be_32(value: &BigUint) -> [u8; 32] {
let be = value.to_bytes_be();
assert!(
be.len() <= 32,
"biguint_to_be_32: value exceeds 32 bytes (>= 2^256)"
);
let mut out = [0u8; 32];
out[32 - be.len()..].copy_from_slice(&be);
out
}
pub fn biguint_to_le_bytes(value: &BigUint, len: usize) -> Vec<u8> {
let mut out = value.to_bytes_le();
assert!(
out.len() <= len,
"biguint_to_le_bytes: value exceeds {len} bytes"
);
out.resize(len, 0);
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hex_matches_node_buffer_from() {
assert_eq!(from_hex("00ff10"), vec![0x00, 0xff, 0x10]);
assert_eq!(from_hex("abc"), vec![0xab]); assert_eq!(from_hex("zz"), Vec::<u8>::new()); assert_eq!(from_hex("0xab"), Vec::<u8>::new()); assert_eq!(from_hex(""), Vec::<u8>::new());
}
#[test]
fn le_conversions() {
let v = BigUint::from(0x0102u32);
assert_eq!(biguint_to_le_bytes(&v, 4), vec![0x02, 0x01, 0x00, 0x00]);
assert_eq!(le_bytes_to_biguint(&[0x02, 0x01, 0x00, 0x00]), v);
}
}