1use super::{CError, DBValue, Result, Trie, TrieHash, TrieIterator, TrieLayout};
16use crate::{
17 nibble::{nibble_ops, NibbleSlice, NibbleVec},
18 node::{Node, NodeHandle, NodePlan, OwnedNode, Value},
19 triedb::TrieDB,
20 TrieDoubleEndedIterator, TrieError, TrieItem, TrieKeyItem,
21};
22use hash_db::{Hasher, Prefix, EMPTY_PREFIX};
23
24use crate::rstd::{boxed::Box, sync::Arc, vec::Vec};
25
26#[cfg_attr(feature = "std", derive(Debug))]
27#[derive(Clone, Copy, Eq, PartialEq)]
28enum Status {
29 Entering,
30 At,
31 AtChild(usize),
32 Exiting,
33 AftExiting,
34}
35
36#[cfg_attr(feature = "std", derive(Debug))]
37#[derive(Eq, PartialEq)]
38struct Crumb<H: Hasher> {
39 hash: Option<H::Out>,
40 node: Arc<OwnedNode<DBValue>>,
41 status: Status,
42}
43
44impl<H: Hasher> Crumb<H> {
45 fn step(&mut self, fwd: bool) {
47 self.status = match (self.status, self.node.node_plan()) {
48 (Status::Entering, NodePlan::Extension { .. }) => Status::At,
49 (Status::Entering, NodePlan::Branch { .. }) |
50 (Status::Entering, NodePlan::NibbledBranch { .. }) => Status::At,
51 (Status::At, NodePlan::Branch { .. }) |
52 (Status::At, NodePlan::NibbledBranch { .. }) =>
53 if fwd {
54 Status::AtChild(0)
55 } else {
56 Status::AtChild(nibble_ops::NIBBLE_LENGTH - 1)
57 },
58 (Status::AtChild(x), NodePlan::Branch { .. }) |
59 (Status::AtChild(x), NodePlan::NibbledBranch { .. })
60 if fwd && x < (nibble_ops::NIBBLE_LENGTH - 1) =>
61 Status::AtChild(x + 1),
62 (Status::AtChild(x), NodePlan::Branch { .. }) |
63 (Status::AtChild(x), NodePlan::NibbledBranch { .. })
64 if !fwd && x > 0 =>
65 Status::AtChild(x - 1),
66 (Status::Exiting, _) => Status::AftExiting,
67 _ => Status::Exiting,
68 }
69 }
70}
71
72pub struct TrieDBRawIterator<L: TrieLayout> {
74 trail: Vec<Crumb<L::Hash>>,
76 key_nibbles: NibbleVec,
78}
79
80impl<L: TrieLayout> TrieDBRawIterator<L> {
81 pub fn empty() -> Self {
83 Self { trail: Vec::new(), key_nibbles: NibbleVec::new() }
84 }
85
86 pub fn new(db: &TrieDB<L>) -> Result<Self, TrieHash<L>, CError<L>> {
88 let mut r =
89 TrieDBRawIterator { trail: Vec::with_capacity(8), key_nibbles: NibbleVec::new() };
90 let (root_node, root_hash) = db.get_raw_or_lookup(
91 *db.root(),
92 NodeHandle::Hash(db.root().as_ref()),
93 EMPTY_PREFIX,
94 true,
95 )?;
96
97 r.descend(root_node, root_hash);
98 Ok(r)
99 }
100
101 pub fn new_prefixed(db: &TrieDB<L>, prefix: &[u8]) -> Result<Self, TrieHash<L>, CError<L>> {
103 let mut iter = TrieDBRawIterator::new(db)?;
104 iter.prefix(db, prefix, true)?;
105
106 Ok(iter)
107 }
108
109 pub fn new_prefixed_then_seek(
113 db: &TrieDB<L>,
114 prefix: &[u8],
115 start_at: &[u8],
116 ) -> Result<Self, TrieHash<L>, CError<L>> {
117 let mut iter = TrieDBRawIterator::new(db)?;
118 iter.prefix_then_seek(db, prefix, start_at)?;
119 Ok(iter)
120 }
121
122 fn descend(&mut self, node: OwnedNode<DBValue>, node_hash: Option<TrieHash<L>>) {
124 self.trail
125 .push(Crumb { hash: node_hash, status: Status::Entering, node: Arc::new(node) });
126 }
127
128 pub(crate) fn fetch_value(
130 db: &TrieDB<L>,
131 key: &[u8],
132 prefix: Prefix,
133 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
134 let mut res = TrieHash::<L>::default();
135 res.as_mut().copy_from_slice(key);
136 db.fetch_value(res, prefix)
137 }
138
139 pub(crate) fn seek(
146 &mut self,
147 db: &TrieDB<L>,
148 key: &[u8],
149 fwd: bool,
150 ) -> Result<bool, TrieHash<L>, CError<L>> {
151 self.trail.clear();
152 self.key_nibbles.clear();
153 let key = NibbleSlice::new(key);
154
155 let (mut node, mut node_hash) = db.get_raw_or_lookup(
156 <TrieHash<L>>::default(),
157 NodeHandle::Hash(db.root().as_ref()),
158 EMPTY_PREFIX,
159 true,
160 )?;
161 let mut partial = key;
162 let mut full_key_nibbles = 0;
163 loop {
164 let (next_node, next_node_hash) = {
165 self.descend(node, node_hash);
166 let crumb = self.trail.last_mut().expect(
167 "descend pushes a crumb onto the trail; \
168 thus the trail is non-empty; qed",
169 );
170 let node_data = crumb.node.data();
171
172 match crumb.node.node_plan() {
173 NodePlan::Leaf { partial: partial_plan, .. } => {
174 let slice = partial_plan.build(node_data);
175 if (fwd && slice < partial) || (!fwd && slice > partial) {
176 crumb.status = Status::AftExiting;
177 return Ok(false);
178 }
179 return Ok(slice.starts_with(&partial));
180 },
181 NodePlan::Extension { partial: partial_plan, child } => {
182 let slice = partial_plan.build(node_data);
183 if !partial.starts_with(&slice) {
184 if (fwd && slice < partial) || (!fwd && slice > partial) {
185 crumb.status = Status::AftExiting;
186 return Ok(false);
187 }
188 return Ok(slice.starts_with(&partial));
189 }
190
191 full_key_nibbles += slice.len();
192 partial = partial.mid(slice.len());
193 crumb.status = Status::At;
194 self.key_nibbles.append_partial(slice.right());
195
196 let prefix = key.back(full_key_nibbles);
197 db.get_raw_or_lookup(
198 node_hash.unwrap_or_default(),
199 child.build(node_data),
200 prefix.left(),
201 true,
202 )?
203 },
204 NodePlan::Branch { value: _, children } => {
205 if partial.is_empty() {
206 return Ok(true);
207 }
208
209 let i = partial.at(0);
210 crumb.status = Status::AtChild(i as usize);
211 self.key_nibbles.push(i);
212
213 if let Some(child) = &children[i as usize] {
214 full_key_nibbles += 1;
215 partial = partial.mid(1);
216
217 let prefix = key.back(full_key_nibbles);
218 db.get_raw_or_lookup(
219 node_hash.unwrap_or_default(),
220 child.build(node_data),
221 prefix.left(),
222 true,
223 )?
224 } else {
225 return Ok(false);
226 }
227 },
228 NodePlan::NibbledBranch { partial: partial_plan, value: _, children } => {
229 let slice = partial_plan.build(node_data);
230 if !partial.starts_with(&slice) {
231 if (fwd && slice < partial) || (!fwd && slice > partial) {
232 crumb.status = Status::AftExiting;
233 return Ok(false);
234 }
235 return Ok(slice.starts_with(&partial));
236 }
237
238 full_key_nibbles += slice.len();
239 partial = partial.mid(slice.len());
240
241 if partial.is_empty() {
242 return Ok(true);
243 }
244
245 let i = partial.at(0);
246 crumb.status = Status::AtChild(i as usize);
247 self.key_nibbles.append_partial(slice.right());
248 self.key_nibbles.push(i);
249
250 if let Some(child) = &children[i as usize] {
251 full_key_nibbles += 1;
252 partial = partial.mid(1);
253
254 let prefix = key.back(full_key_nibbles);
255 db.get_raw_or_lookup(
256 node_hash.unwrap_or_default(),
257 child.build(node_data),
258 prefix.left(),
259 true,
260 )?
261 } else {
262 return Ok(false);
263 }
264 },
265 NodePlan::Empty => {
266 if !partial.is_empty() {
267 crumb.status = Status::Exiting;
268 return Ok(false);
269 }
270 return Ok(true);
271 },
272 }
273 };
274
275 node = next_node;
276 node_hash = next_node_hash;
277 }
278 }
279
280 fn prefix(
283 &mut self,
284 db: &TrieDB<L>,
285 prefix: &[u8],
286 fwd: bool,
287 ) -> Result<(), TrieHash<L>, CError<L>> {
288 if self.seek(db, prefix, fwd)? {
289 if let Some(v) = self.trail.pop() {
290 self.trail.clear();
291 self.trail.push(v);
292 }
293 } else {
294 self.trail.clear();
295 }
296
297 Ok(())
298 }
299
300 fn prefix_then_seek(
303 &mut self,
304 db: &TrieDB<L>,
305 prefix: &[u8],
306 seek: &[u8],
307 ) -> Result<(), TrieHash<L>, CError<L>> {
308 if prefix.is_empty() {
309 return self.seek(db, seek, true).map(|_| ());
311 }
312
313 if seek.is_empty() || seek <= prefix {
314 return self.prefix(db, prefix, true);
318 }
319
320 if !seek.starts_with(prefix) {
321 self.trail.clear();
324 return Ok(());
325 }
326
327 if !self.seek(db, prefix, true)? {
328 self.trail.clear();
330 return Ok(());
331 }
332
333 self.seek(db, seek, true)?;
335
336 let prefix_len = prefix.len() * crate::nibble::nibble_ops::NIBBLE_PER_BYTE;
337 let mut len = 0;
338 for i in 0..self.trail.len() {
340 match self.trail[i].node.node_plan() {
341 NodePlan::Empty => {},
342 NodePlan::Branch { .. } => {
343 len += 1;
344 },
345 NodePlan::Leaf { partial, .. } => {
346 len += partial.len();
347 },
348 NodePlan::Extension { partial, .. } => {
349 len += partial.len();
350 },
351 NodePlan::NibbledBranch { partial, .. } => {
352 len += 1;
353 len += partial.len();
354 },
355 }
356 if len > prefix_len {
357 self.trail = self.trail.split_off(i);
358 return Ok(());
359 }
360 }
361
362 self.trail.clear();
363 Ok(())
364 }
365
366 pub(crate) fn next_raw_item(
372 &mut self,
373 db: &TrieDB<L>,
374 fwd: bool,
375 ) -> Option<
376 Result<
377 (&NibbleVec, Option<&TrieHash<L>>, &Arc<OwnedNode<DBValue>>),
378 TrieHash<L>,
379 CError<L>,
380 >,
381 > {
382 loop {
383 let crumb = self.trail.last_mut()?;
384 let node_data = crumb.node.data();
385
386 match (crumb.status, crumb.node.node_plan()) {
387 (Status::Entering, _) =>
388 if fwd {
389 let crumb = self.trail.last_mut().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
390 crumb.step(fwd);
391 return Some(Ok((&self.key_nibbles, crumb.hash.as_ref(), &crumb.node)));
392 } else {
393 crumb.step(fwd);
394 },
395 (Status::AftExiting, _) => {
396 self.trail.pop().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
397 self.trail.last_mut()?.step(fwd);
398 },
399 (Status::Exiting, node) => {
400 match node {
401 NodePlan::Empty | NodePlan::Leaf { .. } => {},
402 NodePlan::Extension { partial, .. } => {
403 self.key_nibbles.drop_lasts(partial.len());
404 },
405 NodePlan::Branch { .. } => {
406 self.key_nibbles.pop();
407 },
408 NodePlan::NibbledBranch { partial, .. } => {
409 self.key_nibbles.drop_lasts(partial.len() + 1);
410 },
411 }
412 self.trail.last_mut()?.step(fwd);
413 if !fwd {
414 let crumb = self.trail.last_mut().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
415 return Some(Ok((&self.key_nibbles, crumb.hash.as_ref(), &crumb.node)));
416 }
417 },
418 (Status::At, NodePlan::Extension { partial: partial_plan, child }) => {
419 let partial = partial_plan.build(node_data);
420 self.key_nibbles.append_partial(partial.right());
421
422 match db.get_raw_or_lookup(
423 crumb.hash.unwrap_or_default(),
424 child.build(node_data),
425 self.key_nibbles.as_prefix(),
426 true,
427 ) {
428 Ok((node, node_hash)) => {
429 self.descend(node, node_hash);
430 },
431 Err(err) => {
432 crumb.step(fwd);
433 return Some(Err(err));
434 },
435 }
436 },
437 (Status::At, NodePlan::Branch { .. }) => {
438 self.key_nibbles.push(if fwd {
439 0
440 } else {
441 (nibble_ops::NIBBLE_LENGTH - 1) as u8
442 });
443 crumb.step(fwd);
444 },
445 (Status::At, NodePlan::NibbledBranch { partial: partial_plan, .. }) => {
446 let partial = partial_plan.build(node_data);
447 self.key_nibbles.append_partial(partial.right());
448 self.key_nibbles.push(if fwd {
449 0
450 } else {
451 (nibble_ops::NIBBLE_LENGTH - 1) as u8
452 });
453 crumb.step(fwd);
454 },
455 (Status::AtChild(i), NodePlan::Branch { children, .. }) |
456 (Status::AtChild(i), NodePlan::NibbledBranch { children, .. }) => {
457 if let Some(child) = &children[i] {
458 self.key_nibbles.pop();
459 self.key_nibbles.push(i as u8);
460
461 match db.get_raw_or_lookup(
462 crumb.hash.unwrap_or_default(),
463 child.build(node_data),
464 self.key_nibbles.as_prefix(),
465 true,
466 ) {
467 Ok((node, node_hash)) => {
468 self.descend(node, node_hash);
469 },
470 Err(err) => {
471 crumb.step(fwd);
472 return Some(Err(err));
473 },
474 }
475 } else {
476 crumb.step(fwd);
477 }
478 },
479 _ => panic!(
480 "Crumb::step and TrieDBNodeIterator are implemented so that \
481 the above arms are the only possible states"
482 ),
483 }
484 }
485 }
486
487 pub fn next_item(&mut self, db: &TrieDB<L>) -> Option<TrieItem<TrieHash<L>, CError<L>>> {
491 while let Some(raw_item) = self.next_raw_item(db, true) {
492 let (key, maybe_extra_nibble, value) = match Self::extract_key_from_raw_item(raw_item) {
493 Some(Ok(k)) => k,
494 Some(Err(err)) => return Some(Err(err)),
495 None => continue,
496 };
497
498 if let Some(extra_nibble) = maybe_extra_nibble {
499 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
500 }
501
502 let value = match value {
503 Value::Node(hash) => match Self::fetch_value(db, &hash, (key.as_slice(), None)) {
504 Ok(value) => value,
505 Err(err) => return Some(Err(err)),
506 },
507 Value::Inline(value) => value.to_vec(),
508 };
509
510 return Some(Ok((key, value)));
511 }
512 None
513 }
514
515 pub fn prev_item(&mut self, db: &TrieDB<L>) -> Option<TrieItem<TrieHash<L>, CError<L>>> {
519 while let Some(raw_item) = self.next_raw_item(db, false) {
520 let (key, maybe_extra_nibble, value) = match Self::extract_key_from_raw_item(raw_item) {
521 Some(Ok(k)) => k,
522 Some(Err(err)) => return Some(Err(err)),
523 None => continue,
524 };
525
526 if let Some(extra_nibble) = maybe_extra_nibble {
527 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
528 }
529
530 let value = match value {
531 Value::Node(hash) => match Self::fetch_value(db, &hash, (key.as_slice(), None)) {
532 Ok(value) => value,
533 Err(err) => return Some(Err(err)),
534 },
535 Value::Inline(value) => value.to_vec(),
536 };
537
538 return Some(Ok((key, value)));
539 }
540 None
541 }
542
543 pub fn next_key(&mut self, db: &TrieDB<L>) -> Option<TrieKeyItem<TrieHash<L>, CError<L>>> {
547 while let Some(raw_item) = self.next_raw_item(db, true) {
548 let (key, maybe_extra_nibble, _) = match Self::extract_key_from_raw_item(raw_item) {
549 Some(Ok(k)) => k,
550 Some(Err(err)) => return Some(Err(err)),
551 None => continue,
552 };
553
554 if let Some(extra_nibble) = maybe_extra_nibble {
555 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
556 }
557
558 return Some(Ok(key));
559 }
560 None
561 }
562
563 pub fn prev_key(&mut self, db: &TrieDB<L>) -> Option<TrieKeyItem<TrieHash<L>, CError<L>>> {
567 while let Some(raw_item) = self.next_raw_item(db, false) {
568 let (key, maybe_extra_nibble, _) = match Self::extract_key_from_raw_item(raw_item) {
569 Some(Ok(k)) => k,
570 Some(Err(err)) => return Some(Err(err)),
571 None => continue,
572 };
573
574 if let Some(extra_nibble) = maybe_extra_nibble {
575 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
576 }
577
578 return Some(Ok(key));
579 }
580 None
581 }
582
583 fn extract_key_from_raw_item<'a>(
588 raw_item: Result<
589 (&NibbleVec, Option<&TrieHash<L>>, &'a Arc<OwnedNode<DBValue>>),
590 TrieHash<L>,
591 CError<L>,
592 >,
593 ) -> Option<Result<(Vec<u8>, Option<u8>, Value<'a>), TrieHash<L>, CError<L>>> {
594 let (prefix, _, node) = match raw_item {
595 Ok(raw_item) => raw_item,
596 Err(err) => return Some(Err(err)),
597 };
598
599 let mut prefix = prefix.clone();
600 let value = match node.node() {
601 Node::Leaf(partial, value) => {
602 prefix.append_partial(partial.right());
603 value
604 },
605 Node::Branch(_, value) => match value {
606 Some(value) => value,
607 None => return None,
608 },
609 Node::NibbledBranch(partial, _, value) => {
610 prefix.append_partial(partial.right());
611 match value {
612 Some(value) => value,
613 None => return None,
614 }
615 },
616 _ => return None,
617 };
618
619 let (key_slice, maybe_extra_nibble) = prefix.as_prefix();
620
621 Some(Ok((key_slice.to_vec(), maybe_extra_nibble, value)))
622 }
623}
624
625pub struct TrieDBNodeIterator<'a, 'cache, L: TrieLayout> {
631 db: &'a TrieDB<'a, 'cache, L>,
632 raw_iter: TrieDBRawIterator<L>,
633}
634
635impl<'a, 'cache, L: TrieLayout> TrieDBNodeIterator<'a, 'cache, L> {
636 pub fn new(db: &'a TrieDB<'a, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
638 Ok(Self { raw_iter: TrieDBRawIterator::new(db)?, db })
639 }
640
641 pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
643 Self { db, raw_iter }
644 }
645
646 pub fn into_raw(self) -> TrieDBRawIterator<L> {
648 self.raw_iter
649 }
650
651 pub fn fetch_value(
653 &self,
654 key: &[u8],
655 prefix: Prefix,
656 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
657 TrieDBRawIterator::fetch_value(self.db, key, prefix)
658 }
659
660 pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
663 self.raw_iter.prefix(self.db, prefix, true)
664 }
665
666 pub fn prefix_then_seek(
669 &mut self,
670 prefix: &[u8],
671 seek: &[u8],
672 ) -> Result<(), TrieHash<L>, CError<L>> {
673 self.raw_iter.prefix_then_seek(self.db, prefix, seek)
674 }
675
676 pub fn db(&self) -> &dyn hash_db::HashDBRef<L::Hash, DBValue> {
678 self.db.db()
679 }
680}
681
682impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBNodeIterator<'a, 'cache, L> {
683 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
684 self.raw_iter.seek(self.db, key, true).map(|_| ())
685 }
686}
687
688impl<'a, 'cache, L: TrieLayout> Iterator for TrieDBNodeIterator<'a, 'cache, L> {
689 type Item =
690 Result<(NibbleVec, Option<TrieHash<L>>, Arc<OwnedNode<DBValue>>), TrieHash<L>, CError<L>>;
691
692 fn next(&mut self) -> Option<Self::Item> {
693 self.raw_iter.next_raw_item(self.db, true).map(|result| {
694 result.map(|(nibble, hash, node)| (nibble.clone(), hash.cloned(), node.clone()))
695 })
696 }
697}
698
699pub struct TrieDBNodeDoubleEndedIterator<'a, 'cache, L: TrieLayout> {
701 db: &'a TrieDB<'a, 'cache, L>,
702 raw_iter: TrieDBRawIterator<L>,
703 back_raw_iter: TrieDBRawIterator<L>,
704}
705
706impl<'a, 'cache, L: TrieLayout> TrieDBNodeDoubleEndedIterator<'a, 'cache, L> {
707 pub fn new(db: &'a TrieDB<'a, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
709 Ok(Self {
710 db,
711 raw_iter: TrieDBRawIterator::new(db)?,
712 back_raw_iter: TrieDBRawIterator::new(db)?,
713 })
714 }
715
716 pub fn from_raw(
718 db: &'a TrieDB<'a, 'cache, L>,
719 raw_iter: TrieDBRawIterator<L>,
720 back_raw_iter: TrieDBRawIterator<L>,
721 ) -> Self {
722 Self { db, raw_iter, back_raw_iter }
723 }
724
725 pub fn into_raw(self) -> TrieDBRawIterator<L> {
727 self.raw_iter
728 }
729
730 pub fn into_raw_back(self) -> TrieDBRawIterator<L> {
732 self.back_raw_iter
733 }
734
735 pub fn fetch_value(
737 &self,
738 key: &[u8],
739 prefix: Prefix,
740 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
741 TrieDBRawIterator::fetch_value(self.db, key, prefix)
742 }
743
744 pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
747 self.raw_iter.prefix(self.db, prefix, true)?;
748 self.back_raw_iter.prefix(self.db, prefix, false)
749 }
750
751 pub fn prefix_then_seek(
754 &mut self,
755 prefix: &[u8],
756 seek: &[u8],
757 ) -> Result<(), TrieHash<L>, CError<L>> {
758 self.raw_iter.prefix_then_seek(self.db, prefix, seek)?;
759 self.back_raw_iter.prefix_then_seek(self.db, prefix, seek)
760 }
761
762 pub fn db(&self) -> &dyn hash_db::HashDBRef<L::Hash, DBValue> {
764 self.db.db()
765 }
766}
767
768impl<L: TrieLayout> TrieDoubleEndedIterator<L> for TrieDBNodeDoubleEndedIterator<'_, '_, L> {}
769
770impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBNodeDoubleEndedIterator<'a, 'cache, L> {
771 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
772 self.raw_iter.seek(self.db, key, true).map(|_| ())?;
773 self.back_raw_iter.seek(self.db, key, false).map(|_| ())
774 }
775}
776
777impl<'a, 'cache, L: TrieLayout> Iterator for TrieDBNodeDoubleEndedIterator<'a, 'cache, L> {
778 type Item =
779 Result<(NibbleVec, Option<TrieHash<L>>, Arc<OwnedNode<DBValue>>), TrieHash<L>, CError<L>>;
780
781 fn next(&mut self) -> Option<Self::Item> {
782 self.raw_iter.next_raw_item(self.db, true).map(|result| {
783 result.map(|(nibble, hash, node)| (nibble.clone(), hash.cloned(), node.clone()))
784 })
785 }
786}
787
788impl<'a, 'cache, L: TrieLayout> DoubleEndedIterator
789 for TrieDBNodeDoubleEndedIterator<'a, 'cache, L>
790{
791 fn next_back(&mut self) -> Option<Self::Item> {
792 self.back_raw_iter.next_raw_item(self.db, false).map(|result| {
793 result.map(|(nibble, hash, node)| (nibble.clone(), hash.cloned(), node.clone()))
794 })
795 }
796}