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
use bigint::H256; use trie::{Change, DatabaseHandle, get, insert, delete}; use TrieMut; pub trait ItemCounter { fn increase(&mut self, key: H256) -> usize; fn decrease(&mut self, key: H256) -> usize; } pub trait DatabaseMut { fn get(&self, key: H256) -> &[u8]; fn set(&mut self, key: H256, value: Option<&[u8]>); } struct DatabaseMutHandle<'a, D: DatabaseMut + 'a>(&'a D); impl<'a, D: DatabaseMut> DatabaseHandle for DatabaseMutHandle<'a, D> { fn get(&self, key: H256) -> Option<&[u8]> { Some(DatabaseMut::get(self.0, key)) } } pub struct TrieCollection<D: DatabaseMut, C: ItemCounter> { database: D, counter: C, } impl<D: DatabaseMut, C: ItemCounter> TrieCollection<D, C> { pub fn new(database: D, counter: C) -> Self { Self { database, counter } } pub fn trie_for<'a>(&'a self, root: H256) -> DatabaseTrieMut<'a, D> { DatabaseTrieMut { database: &self.database, change: Change::default(), root: root } } pub fn apply<'a>(&'a mut self, trie: DatabaseTrieMut<'a, D>) { for (key, value) in trie.change.adds { self.database.set(key, Some(&value)); self.counter.increase(key); } for key in trie.change.removes { let r = self.counter.decrease(key); if r == 0 { self.database.set(key, None); } } } } pub struct DatabaseTrieMut<'a, D: DatabaseMut + 'a> { database: &'a D, change: Change, root: H256, } impl<'a, D: DatabaseMut> TrieMut for DatabaseTrieMut<'a, D> { fn root(&self) -> H256 { self.root } fn insert(&mut self, key: &[u8], value: &[u8]) { let (new_root, change) = insert(self.root, &DatabaseMutHandle(self.database), key, value).unwrap(); self.change.merge(&change); self.root = new_root; } fn delete(&mut self, key: &[u8]) { let (new_root, change) = delete(self.root, &DatabaseMutHandle(self.database), key).unwrap(); self.change.merge(&change); self.root = new_root; } fn get(&self, key: &[u8]) -> Option<Vec<u8>> { get(self.root, &DatabaseMutHandle(self.database), key).unwrap().map(|v| v.into()) } }