elrond-wasm-debug 0.6.2

Elrond WebAssembly smart contract API debugging mocks and utils
Documentation

//use crate::big_int_mock::*;

use core::ops::{Add, Sub, Mul, Div, Rem};
use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
use core::ops::{BitAnd, BitOr, BitXor, Shr, Shl};
use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShrAssign, ShlAssign};
use alloc::vec::Vec;
use elrond_wasm::BigUintApi;

use num_bigint::BigInt;
use core::cmp::Ordering;

#[derive(Debug)]
pub struct RustBigUint(pub num_bigint::BigInt);

impl RustBigUint {
    pub fn value(&self) -> &BigInt {
        &self.0
    }
}

impl From<u64> for RustBigUint {
    fn from(item: u64) -> Self {
        RustBigUint((item as i64).into())
    }
}

impl From<u32> for RustBigUint {
    fn from(item: u32) -> Self {
        RustBigUint((item as i32).into())
    }
}

impl From<usize> for RustBigUint {
    fn from(item: usize) -> Self {
        RustBigUint((item as i32).into())
    }
}

impl From<BigInt> for RustBigUint {
    fn from(item: BigInt) -> Self {
        RustBigUint(item)
    }
}

impl Clone for RustBigUint {
    fn clone(&self) -> Self {
        RustBigUint(self.0.clone())
    }
}

macro_rules! binary_operator {
    ($trait:ident, $method:ident) => {
        impl $trait for RustBigUint {
            type Output = RustBigUint;
        
            fn $method(self, other: RustBigUint) -> RustBigUint {
                RustBigUint((self.0).$method(other.0))
            }
        }

        impl<'a, 'b> $trait<&'b RustBigUint> for &'a RustBigUint {
            type Output = RustBigUint;
        
            fn $method(self, other: &RustBigUint) -> RustBigUint {
                RustBigUint(self.0.clone().$method(other.0.clone()))
            }
        }
    }
}

binary_operator!{Add, add}
binary_operator!{Mul, mul}
binary_operator!{Div, div}
binary_operator!{Rem, rem}

binary_operator!{BitAnd, bitand}
binary_operator!{BitOr, bitor}
binary_operator!{BitXor, bitxor}

fn check_sub_result(result: &BigInt) {
    if result.sign() == num_bigint::Sign::Minus {
        panic!(b"Cannot subtract because result would be negative")
    }
}

impl Sub for RustBigUint {
    type Output = RustBigUint;

    fn sub(self, other: RustBigUint) -> RustBigUint {
        let result = self.0 - other.0;
        check_sub_result(&result);
        RustBigUint(result)
    }
}

impl<'a, 'b> Sub<&'b RustBigUint> for &'a RustBigUint {
    type Output = RustBigUint;

    fn sub(self, other: &RustBigUint) -> RustBigUint {
        let result = self.0.clone().sub(other.0.clone());
        check_sub_result(&result);
        RustBigUint(result)
    }
}

macro_rules! binary_assign_operator {
    ($trait:ident, $method:ident) => {
        impl $trait<RustBigUint> for RustBigUint {
            fn $method(&mut self, other: Self) {
                BigInt::$method(&mut self.0, other.0);
            }
        }
        
        impl $trait<&RustBigUint> for RustBigUint {
            fn $method(&mut self, other: &RustBigUint) {
                BigInt::$method(&mut self.0, &other.0);
            }
        }
    }
}

binary_assign_operator!{AddAssign, add_assign}
binary_assign_operator!{MulAssign, mul_assign}
binary_assign_operator!{DivAssign, div_assign}
binary_assign_operator!{RemAssign, rem_assign}

binary_assign_operator!{BitAndAssign, bitand_assign}
binary_assign_operator!{BitOrAssign,  bitor_assign}
binary_assign_operator!{BitXorAssign, bitxor_assign}

impl SubAssign<RustBigUint> for RustBigUint {
    fn sub_assign(&mut self, other: Self) {
        BigInt::sub_assign(&mut self.0, other.0);
        check_sub_result(&self.0);
    }
}

impl SubAssign<&RustBigUint> for RustBigUint {
    fn sub_assign(&mut self, other: &RustBigUint) {
        BigInt::sub_assign(&mut self.0, &other.0);
        check_sub_result(&self.0);
    }
}

macro_rules! shift_traits {
    ($shift_trait:ident, $method:ident) => {
        impl $shift_trait<usize> for RustBigUint {
            type Output = RustBigUint;

            fn $method(self, rhs: usize) -> RustBigUint {
                let result = $shift_trait::$method(self.0, rhs);
                RustBigUint(result)
            }
        }
        
        impl<'a> $shift_trait<usize> for &'a RustBigUint {
            type Output = RustBigUint;

            fn $method(self, rhs: usize) -> RustBigUint {
                let result = $shift_trait::$method(&self.0, rhs);
                RustBigUint(result)
            }
        }
    }
}

shift_traits!{Shl, shl}
shift_traits!{Shr, shr}

macro_rules! shift_assign_traits {
    ($shift_assign_trait:ident, $method:ident) => {
        impl $shift_assign_trait<usize> for RustBigUint {
            fn $method(&mut self, rhs: usize) {
                $shift_assign_trait::$method(&mut self.0, rhs);
            }
        }
    }
}

shift_assign_traits!{ShlAssign, shl_assign}
shift_assign_traits!{ShrAssign, shr_assign}



impl PartialEq<Self> for RustBigUint {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        PartialEq::eq(&self.0, &other.0)
    }
}

impl Eq for RustBigUint{}

impl PartialOrd<Self> for RustBigUint {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        PartialOrd::partial_cmp(&self.0, &other.0)
    }
}

impl Ord for RustBigUint {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        Ord::cmp(&self.0, &other.0)
    }
}

impl PartialEq<u64> for RustBigUint {
    #[inline]
    fn eq(&self, other: &u64) -> bool {
        PartialEq::eq(&self.0, &BigInt::from(*other as i64))
    }
}

impl PartialOrd<u64> for RustBigUint {
    #[inline]
    fn partial_cmp(&self, other: &u64) -> Option<Ordering> {
        PartialOrd::partial_cmp(&self.0, &BigInt::from(*other as i64))
    }
}

use elrond_wasm::elrond_codec::*;

impl Encode for RustBigUint {
    const TYPE_INFO: TypeInfo = TypeInfo::BigUint;

    fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
        let bytes = self.to_bytes_be();
        f(&bytes);
        Ok(())
    }
    
    fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
        let bytes = self.to_bytes_be();
        bytes.as_slice().dep_encode_to(dest)
    }
}

impl Decode for RustBigUint {
    const TYPE_INFO: TypeInfo = TypeInfo::BigUint;
    
    fn top_decode<I: Input>(input: &mut I) -> Result<Self, DecodeError> {
        let bytes = input.flush()?;
        Ok(RustBigUint::from_bytes_be(bytes))
    }

    fn dep_decode<I: Input>(input: &mut I) -> Result<Self, DecodeError> {
        let size = usize::dep_decode(input)?;
        let bytes = input.read_slice(size)?;
        Ok(RustBigUint::from_bytes_be(bytes))
    }
}

impl elrond_wasm::BigUintApi for RustBigUint {

    fn byte_length(&self) -> i32 {
        panic!("byte_length not yet implemented")
    }

    fn copy_to_slice_big_endian(&self, _slice: &mut [u8]) -> i32 {
        panic!("copy_to_slice not yet implemented")
    }

    fn copy_to_array_big_endian_pad_right(&self, _target: &mut [u8; 32]) {
        panic!("copy_to_array_big_endian_pad_right not yet implemented")
    }

    fn to_bytes_be(&self) -> Vec<u8> {
        let (_, be) = self.0.to_bytes_be();
        be
    }

    fn to_bytes_be_pad_right(&self, nr_bytes: usize) -> Option<Vec<u8>> {
        let (_, bytes_be) = self.0.to_bytes_be();
        match bytes_be.len().cmp(&nr_bytes) {
            Ordering::Greater => None,
            Ordering::Equal => Some(bytes_be),
            Ordering::Less => {
                let mut res = vec![0u8; nr_bytes];
                let offset = nr_bytes - bytes_be.len();
                res[offset..(bytes_be.len()-1 + offset)].clone_from_slice(&bytes_be[..bytes_be.len()-1]);
                Some(res)
            }
        }
    }

    fn from_bytes_be(bytes: &[u8]) -> Self {
        let bi = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
        bi.into()
    }
}