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
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
use serde::{Deserialize, Deserializer, Serialize};
#[cfg(target_arch = "wasm32")]
use std::convert::TryInto;

use super::errors::ContractError::ContractSizeError;

pub type FunctionSignature = [u8; 4];

pub struct Contract {
    pub data_size: usize,
    pub input_data: Vec<u8>,
    fn_sig: FunctionSignature,
}

impl Contract {
    pub fn new() -> anyhow::Result<Self> {
        #[cfg(target_arch = "wasm32")]
        let data_size = ewasm_api::calldata_size();
        #[cfg(not(target_arch = "wasm32"))]
        let data_size = 0;

        #[cfg(target_arch = "wasm32")]
        let input_data = ewasm_api::calldata_acquire();
        #[cfg(not(target_arch = "wasm32"))]
        let input_data = Vec::new();

        #[cfg(target_arch = "wasm32")]
        let fn_sig = input_data[0..4]
            .try_into()
            .expect("size greator than 4 after validated");
        #[cfg(not(target_arch = "wasm32"))]
        let fn_sig = [0, 0, 0, 0];

        if data_size < 4 {
            Err(ContractSizeError(data_size).into())
        } else {
            Ok(Contract {
                data_size,
                input_data,
                fn_sig,
            })
        }
    }
    pub fn get_function_selector(&self) -> anyhow::Result<FunctionSignature> {
        Ok(self.fn_sig)
    }
    pub fn mock() -> Self {
        let data_size = 5;
        let input_data = vec![0, 0, 0, 0, 0];
        let fn_sig = [0, 0, 0, 0];
        Contract {
            data_size,
            input_data,
            fn_sig,
        }
    }
}

/// helps you return different type of date in the contract handlers
/// The any serializable data can easy to become EwasmAny by following command
/// `EwasmAny::from(instance)`
/// and the data will preserialized and store in the EwasmAny structure,
/// once the `ewasm_main` function try to return the instance of EwasmAny, the preserialized data
/// will be returned.
pub struct EwasmAny {
    pub bin: Vec<u8>,
}

impl EwasmAny {
    pub fn from<T: Serialize>(instance: T) -> Self {
        Self {
            bin: bincode::serialize(&instance).expect("The input should be serializable"),
        }
    }
}

impl<T> From<T> for EwasmAny
where
    T: Serialize,
{
    fn from(i: T) -> Self {
        Self {
            bin: bincode::serialize(&i).unwrap(),
        }
    }
}

// impl Serialize for EwasmAny {
//     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
//     where
//         S: Serializer,
//     {
//         self.bin.serialize(serializer)
//     }
// }

impl<'de> Deserialize<'de> for EwasmAny {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        Deserialize::deserialize(deserializer).map(|bin: Vec<u8>| EwasmAny { bin })
    }
}