tetsy_trie_db/
fatdb.rs

1// Copyright 2017, 2020 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use tetsy_hash_db::{HashDBRef, Hasher};
16use super::{Result, DBValue, TrieDB, Trie, TrieDBIterator, TrieItem, TrieIterator, Query,
17	TrieLayout, CError, TrieHash};
18
19use crate::rstd::boxed::Box;
20
21/// A `Trie` implementation which hashes keys and uses a generic `HashDB` backing database.
22/// Additionaly it stores inserted hash-key mappings for later retrieval.
23///
24/// Use it as a `Trie` or `TrieMut` trait object.
25pub struct FatDB<'db, L>
26where
27	L: TrieLayout,
28{
29	raw: TrieDB<'db, L>,
30}
31
32impl<'db, L> FatDB<'db, L>
33where
34	L: TrieLayout,
35{
36	/// Create a new trie with the backing database `db` and empty `root`
37	/// Initialise to the state entailed by the genesis block.
38	/// This guarantees the trie is built correctly.
39	pub fn new(
40		db: &'db dyn HashDBRef<L::Hash, DBValue>,
41		root: &'db TrieHash<L>,
42	) -> Result<Self, TrieHash<L>, CError<L>> {
43		Ok(FatDB { raw: TrieDB::new(db, root)? })
44	}
45
46	/// Get the backing database.
47	pub fn db(&self) -> &dyn HashDBRef<L::Hash, DBValue> { self.raw.db() }
48}
49
50impl<'db, L> Trie<L> for FatDB<'db, L>
51where
52	L: TrieLayout,
53{
54	fn root(&self) -> &TrieHash<L> { self.raw.root() }
55
56	fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
57		self.raw.contains(L::Hash::hash(key).as_ref())
58	}
59
60	fn get_with<'a, 'key, Q: Query<L::Hash>>(&'a self, key: &'key [u8], query: Q)
61		-> Result<Option<Q::Item>, TrieHash<L>, CError<L>>
62		where 'a: 'key
63	{
64		self.raw.get_with(L::Hash::hash(key).as_ref(), query)
65	}
66
67	fn iter<'a>(&'a self) -> Result<
68		Box<dyn TrieIterator<L, Item = TrieItem<TrieHash<L>, CError<L>>> + 'a>,
69		TrieHash<L>,
70		CError<L>,
71	> {
72		FatDBIterator::<L>::new(&self.raw).map(|iter| Box::new(iter) as Box<_>)
73	}
74}
75
76/// Itarator over inserted pairs of key values.
77pub struct FatDBIterator<'db, L>
78where
79	L: TrieLayout,
80{
81	trie_iterator: TrieDBIterator<'db, L>,
82	trie: &'db TrieDB<'db, L>,
83}
84
85impl<'db, L> FatDBIterator<'db, L>
86where
87	L: TrieLayout,
88{
89	/// Creates new iterator.
90	pub fn new(trie: &'db TrieDB<L>) -> Result<Self, TrieHash<L>, CError<L>> {
91		Ok(FatDBIterator {
92			trie_iterator: TrieDBIterator::new(trie)?,
93			trie,
94		})
95	}
96}
97
98impl<'db, L> TrieIterator<L> for FatDBIterator<'db, L>
99where
100	L: TrieLayout,
101{
102	fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
103		let hashed_key = L::Hash::hash(key);
104		self.trie_iterator.seek(hashed_key.as_ref())
105	}
106}
107
108impl<'db, L> Iterator for FatDBIterator<'db, L>
109where
110	L: TrieLayout,
111{
112	type Item = TrieItem<'db, TrieHash<L>, CError<L>>;
113
114	fn next(&mut self) -> Option<Self::Item> {
115		self.trie_iterator.next()
116			.map(|res| {
117				res.map(|(hash, value)| {
118					let aux_hash = L::Hash::hash(&hash);
119					(
120						self.trie.db().get(&aux_hash, Default::default())
121							.expect("Missing fatdb hash"),
122						value,
123					)
124				})
125			})
126	}
127}