use core::fmt;
use ethabi::Token;
use ethereum_types::U256;
use num_bigint::BigInt;
use crate::contract::{tokens::Tokenizable, Error};
pub struct I256(pub BigInt);
impl Tokenizable for I256 {
fn from_token(token: Token) -> Result<Self, Error>
where
Self: Sized,
{
match token {
Token::Int(val) => {
let bigint = to_bigint_from_u256(val);
Ok(I256(bigint))
},
_ => Err(Error::InvalidOutputType("Expected int".to_owned())),
}
}
#[inline(always)]
fn into_token(self) -> Token {
unimplemented!()
}
}
impl fmt::Display for I256 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.to_string())
}
}
impl fmt::Debug for I256 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "I256({})", self.0)
}
}
fn to_bigint_from_u256(val: U256) -> BigInt {
let mut bytes = [0u8; 32];
val.to_big_endian(&mut bytes);
BigInt::from_signed_bytes_be(&bytes)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_i256_display() {
let val = I256(BigInt::from(-123));
assert_eq!(val.to_string(), "-123");
}
#[test]
fn test_i256_debug() {
let val = I256(BigInt::from(-123));
assert_eq!(format!("{:?}", val), "I256(-123)");
}
#[test]
fn test_to_max_bigint_from_u256() {
let val = U256::MAX / U256::from("2"); let bigint = to_bigint_from_u256(val);
assert_eq!(
format!("{:?}", bigint),
"57896044618658097711785492504343953926634992332820282019728792003956564819967"
)
}
#[test]
fn test_to_min_bigint_from_u256() {
let val = U256::MAX / U256::from("2") + U256::one(); let bigint = to_bigint_from_u256(val);
assert_eq!(
format!("{:?}", bigint),
"-57896044618658097711785492504343953926634992332820282019728792003956564819968"
)
}
}