1use bigint::H256;
2use trie::{Change, DatabaseHandle, get, insert, delete};
3use TrieMut;
4
5pub trait ItemCounter {
6 fn increase(&mut self, key: H256) -> usize;
7 fn decrease(&mut self, key: H256) -> usize;
8}
9
10pub trait DatabaseMut {
11 fn get(&self, key: H256) -> &[u8];
12 fn set(&mut self, key: H256, value: Option<&[u8]>);
13}
14
15struct DatabaseMutHandle<'a, D: DatabaseMut + 'a>(&'a D);
16
17impl<'a, D: DatabaseMut> DatabaseHandle for DatabaseMutHandle<'a, D> {
18 fn get(&self, key: H256) -> Option<&[u8]> {
19 Some(DatabaseMut::get(self.0, key))
20 }
21}
22
23pub struct TrieCollection<D: DatabaseMut, C: ItemCounter> {
24 database: D,
25 counter: C,
26}
27
28impl<D: DatabaseMut, C: ItemCounter> TrieCollection<D, C> {
29 pub fn new(database: D, counter: C) -> Self {
30 Self { database, counter }
31 }
32
33 pub fn trie_for<'a>(&'a self, root: H256) -> DatabaseTrieMut<'a, D> {
34 DatabaseTrieMut {
35 database: &self.database,
36 change: Change::default(),
37 root: root
38 }
39 }
40
41 pub fn apply<'a>(&'a mut self, trie: DatabaseTrieMut<'a, D>) {
42 for (key, value) in trie.change.adds {
43 self.database.set(key, Some(&value));
44 self.counter.increase(key);
45 }
46
47 for key in trie.change.removes {
48 let r = self.counter.decrease(key);
49 if r == 0 {
50 self.database.set(key, None);
51 }
52 }
53 }
54}
55
56pub struct DatabaseTrieMut<'a, D: DatabaseMut + 'a> {
57 database: &'a D,
58 change: Change,
59 root: H256,
60}
61
62impl<'a, D: DatabaseMut> TrieMut for DatabaseTrieMut<'a, D> {
63 fn root(&self) -> H256 {
64 self.root
65 }
66
67 fn insert(&mut self, key: &[u8], value: &[u8]) {
68 let (new_root, change) = insert(self.root, &DatabaseMutHandle(self.database), key, value).unwrap();
69
70 self.change.merge(&change);
71 self.root = new_root;
72 }
73
74 fn delete(&mut self, key: &[u8]) {
75 let (new_root, change) = delete(self.root, &DatabaseMutHandle(self.database), key).unwrap();
76
77 self.change.merge(&change);
78 self.root = new_root;
79 }
80
81 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
82 get(self.root, &DatabaseMutHandle(self.database), key).unwrap().map(|v| v.into())
83 }
84}