fvm_std/
spread.rs

1use crate::runtime;
2use scale::{Decode, Encode};
3
4/// Types that can be stored to and loaded from the contract storage.
5/// 合约中的每一个属性都会生成下面的接口,有了这个接口,各个属性便可以单独序列化到db中
6pub trait SpreadLayout {
7    /// 从账本读数据接口
8    fn read_ledger(key: &[u8], prefix: &[u8]) -> Self;
9
10    /// 写入账本数据接口,key为属性名
11    fn write_ledger(&self, key: &[u8], prefix: &[u8]);
12}
13
14
15// todo: delete implement `Default` interface and change return `Option<Self>`
16// 这个实现应该是宏来完成的,因为需要联系上每个变量的名称
17impl<T> SpreadLayout for T where T: Encode + Decode + Default {
18    fn read_ledger(key: &[u8], _: &[u8]) -> Self {
19        // key 的拼接规则: contractAddress + `_` + paramName
20        // value 的规则:value.encode();
21        match runtime::storage_read(key, "".as_bytes()) {
22            Some(value) => {
23                <T>::decode(&mut &value[..]).unwrap()
24            }
25            None => { Default::default() }
26        }
27    }
28
29    // the prefix is for Composite Structure like `Hypermap`, no use there
30    fn write_ledger(&self, key: &[u8], _: &[u8]) {
31        runtime::storage_write(key, "".as_bytes(), self.encode().as_mut_slice())
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use alloc::string::String;
38    use crate::spread::SpreadLayout;
39
40    #[test]
41    fn test_spread_layout() {
42        let _mock = fvm_mock::build_runtime();
43        let a = 10;
44        let b = String::from("test");
45        a.write_ledger("key_a".as_bytes(), &[]);
46        b.write_ledger("key_b".as_bytes(), &[]);
47
48        let aa: i32 = SpreadLayout::read_ledger("key_a".as_bytes(), &[]);
49        let bb: String = SpreadLayout::read_ledger("key_b".as_bytes(), &[]);
50        assert_eq!(a, aa);
51        assert_eq!(b, bb);
52    }
53}