casper_contract_sdk/collections/
map.rs1use crate::{
2 abi::{CasperABI, Declaration, Definition, StructField},
3 casper::{self, read_into_vec},
4 serializers::borsh::{BorshDeserialize, BorshSerialize},
5};
6use casper_executor_wasm_common::keyspace::Keyspace;
7use const_fnv1a_hash::fnv1a_hash_str_64;
8
9use crate::prelude::marker::PhantomData;
10
11#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)]
12#[borsh(crate = "crate::serializers::borsh")]
13pub struct Map<K, V> {
14 pub(crate) name: String,
15 pub(crate) _marker: PhantomData<(K, V)>,
16}
17
18#[allow(dead_code)]
20pub(crate) const fn compute_prefix(input: &str) -> [u8; 8] {
21 let hash = fnv1a_hash_str_64(input);
22 hash.to_le_bytes()
23}
24
25impl<K, V> Map<K, V>
26where
27 K: BorshSerialize,
28 V: BorshSerialize + BorshDeserialize,
29{
30 pub fn new<S: Into<String>>(name: S) -> Self {
31 Self {
32 name: name.into(),
33 _marker: PhantomData,
34 }
35 }
36
37 pub fn insert(&mut self, key: &K, value: &V) {
38 let mut context_key = Vec::new();
39 context_key.extend(self.name.as_bytes());
40 key.serialize(&mut context_key).unwrap();
43 let prefix = Keyspace::Context(&context_key);
44 casper::write(prefix, &borsh::to_vec(value).unwrap()).unwrap();
45 }
46
47 pub fn remove(&mut self, key: &K) {
48 let prefix_bytes = self.compute_prefix_for_key(key);
49 let prefix = Keyspace::Context(&prefix_bytes);
50 casper::remove(prefix).unwrap();
51 }
52
53 pub fn get(&self, key: &K) -> Option<V> {
54 let mut key_bytes = self.name.as_bytes().to_owned();
55 key.serialize(&mut key_bytes).unwrap();
56 let prefix = Keyspace::Context(&key_bytes);
57 read_into_vec(prefix)
58 .unwrap()
59 .map(|vec| borsh::from_slice(&vec).unwrap())
60 }
61
62 fn compute_prefix_for_key(&self, key: &K) -> Vec<u8> {
63 let mut context_key = Vec::new();
64 context_key.extend(self.name.as_bytes());
65 key.serialize(&mut context_key).unwrap();
66 context_key
67 }
68}
69
70impl<K: CasperABI, V: CasperABI> CasperABI for Map<K, V> {
71 fn populate_definitions(definitions: &mut crate::abi::Definitions) {
72 definitions.populate_one::<K>();
73 definitions.populate_one::<V>();
74 }
75
76 fn declaration() -> Declaration {
77 format!("Map<{}, {}>", K::declaration(), V::declaration())
78 }
79 #[inline]
80 fn definition() -> Definition {
81 Definition::Struct {
82 items: vec![StructField {
83 name: "prefix".into(),
84 decl: u64::declaration(),
85 }],
86 }
87 }
88}
89
90#[cfg(test)]
91pub(crate) mod tests {
92 use super::*;
93
94 #[test]
95 fn test_compute_prefix() {
96 let prefix = compute_prefix("hello");
97 assert_eq!(prefix.as_slice(), &[11, 189, 170, 128, 70, 216, 48, 164]);
98 let back = u64::from_le_bytes(prefix);
99 assert_eq!(fnv1a_hash_str_64("hello"), back);
100 }
101
102 #[ignore]
103 #[test]
104 fn test_map() {
105 let mut map = Map::<u64, u64>::new("test");
106 map.insert(&1, &2);
107 assert_eq!(map.get(&1), Some(2));
108 assert_eq!(map.get(&2), None);
109 map.insert(&2, &3);
110 assert_eq!(map.get(&1), Some(2));
111 assert_eq!(map.get(&2), Some(3));
112
113 let mut map = Map::<u64, u64>::new("test2");
114 assert_eq!(map.get(&1), None);
115 map.insert(&1, &22);
116 assert_eq!(map.get(&1), Some(22));
117 assert_eq!(map.get(&2), None);
118 map.insert(&2, &33);
119 assert_eq!(map.get(&1), Some(22));
120 assert_eq!(map.get(&2), Some(33));
121 }
122}