fvm-std 1.0.0

tool for user to write contract which will be run in hyperchain with rust
Documentation
use crate::runtime;
use scale::{Decode, Encode};

/// Types that can be stored to and loaded from the contract storage.
/// 合约中的每一个属性都会生成下面的接口,有了这个接口,各个属性便可以单独序列化到db中
pub trait SpreadLayout {
    /// 从账本读数据接口
    fn read_ledger(key: &[u8], prefix: &[u8]) -> Self;

    /// 写入账本数据接口,key为属性名
    fn write_ledger(&self, key: &[u8], prefix: &[u8]);
}


// todo: delete implement `Default` interface and change return `Option<Self>`
// 这个实现应该是宏来完成的,因为需要联系上每个变量的名称
impl<T> SpreadLayout for T where T: Encode + Decode + Default {
    fn read_ledger(key: &[u8], _: &[u8]) -> Self {
        // key 的拼接规则: contractAddress + `_` + paramName
        // value 的规则:value.encode();
        match runtime::storage_read(key, "".as_bytes()) {
            Some(value) => {
                <T>::decode(&mut &value[..]).unwrap()
            }
            None => { Default::default() }
        }
    }

    // the prefix is for Composite Structure like `Hypermap`, no use there
    fn write_ledger(&self, key: &[u8], _: &[u8]) {
        runtime::storage_write(key, "".as_bytes(), self.encode().as_mut_slice())
    }
}

#[cfg(test)]
mod tests {
    use alloc::string::String;
    use crate::spread::SpreadLayout;

    #[test]
    fn test_spread_layout() {
        let _mock = fvm_mock::build_runtime();
        let a = 10;
        let b = String::from("test");
        a.write_ledger("key_a".as_bytes(), &[]);
        b.write_ledger("key_b".as_bytes(), &[]);

        let aa: i32 = SpreadLayout::read_ledger("key_a".as_bytes(), &[]);
        let bb: String = SpreadLayout::read_ledger("key_b".as_bytes(), &[]);
        assert_eq!(a, aa);
        assert_eq!(b, bb);
    }
}