soroban_env_host/host/
num.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#[macro_export]
macro_rules! impl_wrapping_obj_from_num {
    ($host_fn: ident, $hot: ty, $obj: ty, $num: ty) => {
        fn $host_fn(&self, _vmcaller: &mut VmCaller<Host>, u: $num) -> Result<$obj, HostError> {
            self.add_host_object(<$hot>::from(u))
        }
    };
}

#[macro_export]
macro_rules! impl_wrapping_obj_to_num {
    ($host_fn: ident, $data: ty, $obj: ty, $num: ty) => {
        fn $host_fn(&self, _vmcaller: &mut VmCaller<Host>, obj: $obj) -> Result<$num, HostError> {
            self.visit_obj(obj, |t: &$data| Ok(t.metered_clone(self)?.into()))
        }
    };
}

#[macro_export]
macro_rules! impl_bignum_host_fns {
    ($host_fn: ident, $method: ident, $num: ty, $valty: ty, $cost: ident) => {
        fn $host_fn(
            &self,
            _vmcaller: &mut VmCaller<Self::VmUserState>,
            lhs_val: $valty,
            rhs_val: $valty,
        ) -> Result<$valty, Self::Error> {
            use soroban_env_common::TryIntoVal;
            self.charge_budget(ContractCostType::$cost, None)?;
            let lhs: $num = lhs_val.to_val().try_into_val(self)?;
            let rhs: $num = rhs_val.to_val().try_into_val(self)?;
            let res: $num = lhs.$method(rhs).ok_or_else(|| {
                self.err(
                    ScErrorType::Object,
                    ScErrorCode::ArithDomain,
                    "overflow has occured",
                    &[lhs_val.to_val(), rhs_val.to_val()],
                )
            })?;
            Ok(res.try_into_val(self)?)
        }
    };
}

#[macro_export]
macro_rules! impl_bignum_host_fns_rhs_u32 {
    ($host_fn: ident, $method: ident, $num: ty, $valty: ty, $cost: ident) => {
        fn $host_fn(
            &self,
            _vmcaller: &mut VmCaller<Self::VmUserState>,
            lhs_val: $valty,
            rhs_val: U32Val,
        ) -> Result<$valty, Self::Error> {
            use soroban_env_common::TryIntoVal;
            self.charge_budget(ContractCostType::$cost, None)?;
            let lhs: $num = lhs_val.to_val().try_into_val(self)?;
            let res = lhs.$method(rhs_val.into()).ok_or_else(|| {
                self.err(
                    ScErrorType::Object,
                    ScErrorCode::ArithDomain,
                    "overflow has occured",
                    &[lhs_val.to_val(), rhs_val.to_val()],
                )
            })?;
            Ok(res.try_into_val(self)?)
        }
    };
}

#[macro_export]
macro_rules! impl_bls12_381_fr_arith_host_fns {
    ($host_fn: ident, $method: ident) => {
        fn $host_fn(
            &self,
            _vmcaller: &mut VmCaller<Self::VmUserState>,
            lhs: U256Val,
            rhs: U256Val,
        ) -> Result<U256Val, Self::Error> {
            let mut lhs = self.fr_from_u256val(lhs)?;
            let rhs = self.fr_from_u256val(rhs)?;
            self.$method(&mut lhs, &rhs)?;
            self.fr_to_u256val(lhs)
        }
    };
}