1use super::{
16 CError, DBValue, Query, Result, Trie, TrieDB, TrieDBIterator, TrieDBKeyIterator, TrieHash,
17 TrieItem, TrieIterator, TrieKeyItem, TrieLayout,
18};
19use hash_db::{HashDBRef, Hasher};
20
21use crate::{rstd::boxed::Box, MerkleValue, TrieDBBuilder};
22
23pub struct FatDB<'db, 'cache, L>
28where
29 L: TrieLayout,
30{
31 raw: TrieDB<'db, 'cache, L>,
32}
33
34impl<'db, 'cache, L> FatDB<'db, 'cache, L>
35where
36 L: TrieLayout,
37{
38 pub fn new(db: &'db dyn HashDBRef<L::Hash, DBValue>, root: &'db TrieHash<L>) -> Self {
42 FatDB { raw: TrieDBBuilder::new(db, root).build() }
43 }
44
45 pub fn db(&self) -> &dyn HashDBRef<L::Hash, DBValue> {
47 self.raw.db()
48 }
49}
50
51impl<'db, 'cache, L> Trie<L> for FatDB<'db, 'cache, L>
52where
53 L: TrieLayout,
54{
55 fn root(&self) -> &TrieHash<L> {
56 self.raw.root()
57 }
58
59 fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
60 self.raw.contains(L::Hash::hash(key).as_ref())
61 }
62
63 fn get_hash(&self, key: &[u8]) -> Result<Option<TrieHash<L>>, TrieHash<L>, CError<L>> {
64 self.raw.get_hash(key)
65 }
66
67 fn get_with<Q: Query<L::Hash>>(
68 &self,
69 key: &[u8],
70 query: Q,
71 ) -> Result<Option<Q::Item>, TrieHash<L>, CError<L>> {
72 self.raw.get_with(L::Hash::hash(key).as_ref(), query)
73 }
74
75 fn lookup_first_descendant(
76 &self,
77 key: &[u8],
78 ) -> Result<Option<MerkleValue<TrieHash<L>>>, TrieHash<L>, CError<L>> {
79 self.raw.lookup_first_descendant(key)
80 }
81
82 fn iter<'a>(
83 &'a self,
84 ) -> Result<
85 Box<dyn TrieIterator<L, Item = TrieItem<TrieHash<L>, CError<L>>> + 'a>,
86 TrieHash<L>,
87 CError<L>,
88 > {
89 FatDBIterator::<L>::new(&self.raw).map(|iter| Box::new(iter) as Box<_>)
90 }
91
92 fn key_iter<'a>(
93 &'a self,
94 ) -> Result<
95 Box<dyn TrieIterator<L, Item = TrieKeyItem<TrieHash<L>, CError<L>>> + 'a>,
96 TrieHash<L>,
97 CError<L>,
98 > {
99 FatDBKeyIterator::<L>::new(&self.raw).map(|iter| Box::new(iter) as Box<_>)
100 }
101}
102
103pub struct FatDBIterator<'db, 'cache, L>
105where
106 L: TrieLayout,
107{
108 trie_iterator: TrieDBIterator<'db, 'cache, L>,
109 trie: &'db TrieDB<'db, 'cache, L>,
110}
111
112impl<'db, 'cache, L> FatDBIterator<'db, 'cache, L>
113where
114 L: TrieLayout,
115{
116 pub fn new(trie: &'db TrieDB<'db, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
118 Ok(FatDBIterator { trie_iterator: TrieDBIterator::new(trie)?, trie })
119 }
120}
121
122impl<'db, 'cache, L> TrieIterator<L> for FatDBIterator<'db, 'cache, L>
123where
124 L: TrieLayout,
125{
126 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
127 let hashed_key = L::Hash::hash(key);
128 self.trie_iterator.seek(hashed_key.as_ref())
129 }
130}
131
132impl<'db, 'cache, L> Iterator for FatDBIterator<'db, 'cache, L>
133where
134 L: TrieLayout,
135{
136 type Item = TrieItem<TrieHash<L>, CError<L>>;
137
138 fn next(&mut self) -> Option<Self::Item> {
139 self.trie_iterator.next().map(|res| {
140 res.map(|(hash, value)| {
141 let aux_hash = L::Hash::hash(&hash);
142 (
143 self.trie.db().get(&aux_hash, Default::default()).expect("Missing fatdb hash"),
144 value,
145 )
146 })
147 })
148 }
149}
150
151pub struct FatDBKeyIterator<'db, 'cache, L>
153where
154 L: TrieLayout,
155{
156 trie_iterator: TrieDBKeyIterator<'db, 'cache, L>,
157 trie: &'db TrieDB<'db, 'cache, L>,
158}
159
160impl<'db, 'cache, L> FatDBKeyIterator<'db, 'cache, L>
161where
162 L: TrieLayout,
163{
164 pub fn new(trie: &'db TrieDB<'db, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
166 Ok(FatDBKeyIterator { trie_iterator: TrieDBKeyIterator::new(trie)?, trie })
167 }
168}
169
170impl<'db, 'cache, L> TrieIterator<L> for FatDBKeyIterator<'db, 'cache, L>
171where
172 L: TrieLayout,
173{
174 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
175 let hashed_key = L::Hash::hash(key);
176 self.trie_iterator.seek(hashed_key.as_ref())
177 }
178}
179
180impl<'db, 'cache, L> Iterator for FatDBKeyIterator<'db, 'cache, L>
181where
182 L: TrieLayout,
183{
184 type Item = TrieKeyItem<TrieHash<L>, CError<L>>;
185
186 fn next(&mut self) -> Option<Self::Item> {
187 self.trie_iterator.next().map(|res| {
188 res.map(|hash| {
189 let aux_hash = L::Hash::hash(&hash);
190 self.trie.db().get(&aux_hash, Default::default()).expect("Missing fatdb hash")
191 })
192 })
193 }
194}