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 skip_current_subtree(&mut self) {
133 if let Some(crumb) = self.trail.last_mut() {
134 crumb.status = Status::AftExiting;
135 }
136 }
137
138 pub(crate) fn fetch_value(
140 db: &TrieDB<L>,
141 key: &[u8],
142 prefix: Prefix,
143 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
144 let mut res = TrieHash::<L>::default();
145 res.as_mut().copy_from_slice(key);
146 db.fetch_value(res, prefix)
147 }
148
149 pub(crate) fn seek(
156 &mut self,
157 db: &TrieDB<L>,
158 key: &[u8],
159 fwd: bool,
160 ) -> Result<bool, TrieHash<L>, CError<L>> {
161 self.trail.clear();
162 self.key_nibbles.clear();
163 let key = NibbleSlice::new(key);
164
165 let (mut node, mut node_hash) = db.get_raw_or_lookup(
166 <TrieHash<L>>::default(),
167 NodeHandle::Hash(db.root().as_ref()),
168 EMPTY_PREFIX,
169 true,
170 )?;
171 let mut partial = key;
172 let mut full_key_nibbles = 0;
173 loop {
174 let (next_node, next_node_hash) = {
175 self.descend(node, node_hash);
176 let crumb = self.trail.last_mut().expect(
177 "descend pushes a crumb onto the trail; \
178 thus the trail is non-empty; qed",
179 );
180 let node_data = crumb.node.data();
181
182 match crumb.node.node_plan() {
183 NodePlan::Leaf { partial: partial_plan, .. } => {
184 let slice = partial_plan.build(node_data);
185 if (fwd && slice < partial) || (!fwd && slice > partial) {
186 crumb.status = Status::AftExiting;
187 return Ok(false);
188 }
189 return Ok(slice.starts_with(&partial));
190 },
191 NodePlan::Extension { partial: partial_plan, child } => {
192 let slice = partial_plan.build(node_data);
193 if !partial.starts_with(&slice) {
194 if (fwd && slice < partial) || (!fwd && slice > partial) {
195 crumb.status = Status::AftExiting;
196 return Ok(false);
197 }
198 return Ok(slice.starts_with(&partial));
199 }
200
201 full_key_nibbles += slice.len();
202 partial = partial.mid(slice.len());
203 crumb.status = Status::At;
204 self.key_nibbles.append_partial(slice.right());
205
206 let prefix = key.back(full_key_nibbles);
207 db.get_raw_or_lookup(
208 node_hash.unwrap_or_default(),
209 child.build(node_data),
210 prefix.left(),
211 true,
212 )?
213 },
214 NodePlan::Branch { value: _, children } => {
215 if partial.is_empty() {
216 return Ok(true);
217 }
218
219 let i = partial.at(0);
220 crumb.status = Status::AtChild(i as usize);
221 self.key_nibbles.push(i);
222
223 if let Some(child) = &children[i as usize] {
224 full_key_nibbles += 1;
225 partial = partial.mid(1);
226
227 let prefix = key.back(full_key_nibbles);
228 db.get_raw_or_lookup(
229 node_hash.unwrap_or_default(),
230 child.build(node_data),
231 prefix.left(),
232 true,
233 )?
234 } else {
235 return Ok(false);
236 }
237 },
238 NodePlan::NibbledBranch { partial: partial_plan, value: _, children } => {
239 let slice = partial_plan.build(node_data);
240 if !partial.starts_with(&slice) {
241 if (fwd && slice < partial) || (!fwd && slice > partial) {
242 crumb.status = Status::AftExiting;
243 return Ok(false);
244 }
245 return Ok(slice.starts_with(&partial));
246 }
247
248 full_key_nibbles += slice.len();
249 partial = partial.mid(slice.len());
250
251 if partial.is_empty() {
252 return Ok(true);
253 }
254
255 let i = partial.at(0);
256 crumb.status = Status::AtChild(i as usize);
257 self.key_nibbles.append_partial(slice.right());
258 self.key_nibbles.push(i);
259
260 if let Some(child) = &children[i as usize] {
261 full_key_nibbles += 1;
262 partial = partial.mid(1);
263
264 let prefix = key.back(full_key_nibbles);
265 db.get_raw_or_lookup(
266 node_hash.unwrap_or_default(),
267 child.build(node_data),
268 prefix.left(),
269 true,
270 )?
271 } else {
272 return Ok(false);
273 }
274 },
275 NodePlan::Empty => {
276 if !partial.is_empty() {
277 crumb.status = Status::Exiting;
278 return Ok(false);
279 }
280 return Ok(true);
281 },
282 }
283 };
284
285 node = next_node;
286 node_hash = next_node_hash;
287 }
288 }
289
290 fn prefix(
293 &mut self,
294 db: &TrieDB<L>,
295 prefix: &[u8],
296 fwd: bool,
297 ) -> Result<(), TrieHash<L>, CError<L>> {
298 if self.seek(db, prefix, fwd)? {
299 if let Some(v) = self.trail.pop() {
300 self.trail.clear();
301 self.trail.push(v);
302 }
303 } else {
304 self.trail.clear();
305 }
306
307 Ok(())
308 }
309
310 fn prefix_then_seek(
313 &mut self,
314 db: &TrieDB<L>,
315 prefix: &[u8],
316 seek: &[u8],
317 ) -> Result<(), TrieHash<L>, CError<L>> {
318 if prefix.is_empty() {
319 return self.seek(db, seek, true).map(|_| ());
321 }
322
323 if seek.is_empty() || seek <= prefix {
324 return self.prefix(db, prefix, true);
328 }
329
330 if !seek.starts_with(prefix) {
331 self.trail.clear();
334 return Ok(());
335 }
336
337 if !self.seek(db, prefix, true)? {
338 self.trail.clear();
340 return Ok(());
341 }
342
343 self.seek(db, seek, true)?;
345
346 let prefix_len = prefix.len() * crate::nibble::nibble_ops::NIBBLE_PER_BYTE;
347 let mut len = 0;
348 for i in 0..self.trail.len() {
350 match self.trail[i].node.node_plan() {
351 NodePlan::Empty => {},
352 NodePlan::Branch { .. } => {
353 len += 1;
354 },
355 NodePlan::Leaf { partial, .. } => {
356 len += partial.len();
357 },
358 NodePlan::Extension { partial, .. } => {
359 len += partial.len();
360 },
361 NodePlan::NibbledBranch { partial, .. } => {
362 len += 1;
363 len += partial.len();
364 },
365 }
366 if len > prefix_len {
367 self.trail = self.trail.split_off(i);
368 return Ok(());
369 }
370 }
371
372 self.trail.clear();
373 Ok(())
374 }
375
376 pub(crate) fn next_raw_item(
382 &mut self,
383 db: &TrieDB<L>,
384 fwd: bool,
385 ) -> Option<
386 Result<
387 (&NibbleVec, Option<&TrieHash<L>>, &Arc<OwnedNode<DBValue>>),
388 TrieHash<L>,
389 CError<L>,
390 >,
391 > {
392 loop {
393 let crumb = self.trail.last_mut()?;
394 let node_data = crumb.node.data();
395
396 match (crumb.status, crumb.node.node_plan()) {
397 (Status::Entering, _) =>
398 if fwd {
399 let crumb = self.trail.last_mut().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
400 crumb.step(fwd);
401 return Some(Ok((&self.key_nibbles, crumb.hash.as_ref(), &crumb.node)));
402 } else {
403 crumb.step(fwd);
404 },
405 (Status::AftExiting, _) => {
406 self.trail.pop().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
407 self.trail.last_mut()?.step(fwd);
408 },
409 (Status::Exiting, node) => {
410 match node {
411 NodePlan::Empty | NodePlan::Leaf { .. } => {},
412 NodePlan::Extension { partial, .. } => {
413 self.key_nibbles.drop_lasts(partial.len());
414 },
415 NodePlan::Branch { .. } => {
416 self.key_nibbles.pop();
417 },
418 NodePlan::NibbledBranch { partial, .. } => {
419 self.key_nibbles.drop_lasts(partial.len() + 1);
420 },
421 }
422 self.trail.last_mut()?.step(fwd);
423 if !fwd {
424 let crumb = self.trail.last_mut().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
425 return Some(Ok((&self.key_nibbles, crumb.hash.as_ref(), &crumb.node)));
426 }
427 },
428 (Status::At, NodePlan::Extension { partial: partial_plan, child }) => {
429 let partial = partial_plan.build(node_data);
430 self.key_nibbles.append_partial(partial.right());
431
432 match db.get_raw_or_lookup(
433 crumb.hash.unwrap_or_default(),
434 child.build(node_data),
435 self.key_nibbles.as_prefix(),
436 true,
437 ) {
438 Ok((node, node_hash)) => {
439 self.descend(node, node_hash);
440 },
441 Err(err) => {
442 crumb.step(fwd);
443 return Some(Err(err));
444 },
445 }
446 },
447 (Status::At, NodePlan::Branch { .. }) => {
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::At, NodePlan::NibbledBranch { partial: partial_plan, .. }) => {
456 let partial = partial_plan.build(node_data);
457 self.key_nibbles.append_partial(partial.right());
458 self.key_nibbles.push(if fwd {
459 0
460 } else {
461 (nibble_ops::NIBBLE_LENGTH - 1) as u8
462 });
463 crumb.step(fwd);
464 },
465 (Status::AtChild(i), NodePlan::Branch { children, .. }) |
466 (Status::AtChild(i), NodePlan::NibbledBranch { children, .. }) => {
467 if let Some(child) = &children[i] {
468 self.key_nibbles.pop();
469 self.key_nibbles.push(i as u8);
470
471 match db.get_raw_or_lookup(
472 crumb.hash.unwrap_or_default(),
473 child.build(node_data),
474 self.key_nibbles.as_prefix(),
475 true,
476 ) {
477 Ok((node, node_hash)) => {
478 self.descend(node, node_hash);
479 },
480 Err(err) => {
481 crumb.step(fwd);
482 return Some(Err(err));
483 },
484 }
485 } else {
486 crumb.step(fwd);
487 }
488 },
489 _ => panic!(
490 "Crumb::step and TrieDBNodeIterator are implemented so that \
491 the above arms are the only possible states"
492 ),
493 }
494 }
495 }
496
497 pub fn next_item(&mut self, db: &TrieDB<L>) -> Option<TrieItem<TrieHash<L>, CError<L>>> {
501 while let Some(raw_item) = self.next_raw_item(db, true) {
502 let (key, maybe_extra_nibble, value) = match Self::extract_key_from_raw_item(raw_item) {
503 Some(Ok(k)) => k,
504 Some(Err(err)) => return Some(Err(err)),
505 None => continue,
506 };
507
508 if let Some(extra_nibble) = maybe_extra_nibble {
509 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
510 }
511
512 let value = match value {
513 Value::Node(hash) => match Self::fetch_value(db, &hash, (key.as_slice(), None)) {
514 Ok(value) => value,
515 Err(err) => return Some(Err(err)),
516 },
517 Value::Inline(value) => value.to_vec(),
518 };
519
520 return Some(Ok((key, value)));
521 }
522 None
523 }
524
525 pub fn prev_item(&mut self, db: &TrieDB<L>) -> Option<TrieItem<TrieHash<L>, CError<L>>> {
529 while let Some(raw_item) = self.next_raw_item(db, false) {
530 let (key, maybe_extra_nibble, value) = match Self::extract_key_from_raw_item(raw_item) {
531 Some(Ok(k)) => k,
532 Some(Err(err)) => return Some(Err(err)),
533 None => continue,
534 };
535
536 if let Some(extra_nibble) = maybe_extra_nibble {
537 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
538 }
539
540 let value = match value {
541 Value::Node(hash) => match Self::fetch_value(db, &hash, (key.as_slice(), None)) {
542 Ok(value) => value,
543 Err(err) => return Some(Err(err)),
544 },
545 Value::Inline(value) => value.to_vec(),
546 };
547
548 return Some(Ok((key, value)));
549 }
550 None
551 }
552
553 pub fn next_key(&mut self, db: &TrieDB<L>) -> Option<TrieKeyItem<TrieHash<L>, CError<L>>> {
557 while let Some(raw_item) = self.next_raw_item(db, true) {
558 let (key, maybe_extra_nibble, _) = match Self::extract_key_from_raw_item(raw_item) {
559 Some(Ok(k)) => k,
560 Some(Err(err)) => return Some(Err(err)),
561 None => continue,
562 };
563
564 if let Some(extra_nibble) = maybe_extra_nibble {
565 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
566 }
567
568 return Some(Ok(key));
569 }
570 None
571 }
572
573 pub fn prev_key(&mut self, db: &TrieDB<L>) -> Option<TrieKeyItem<TrieHash<L>, CError<L>>> {
577 while let Some(raw_item) = self.next_raw_item(db, false) {
578 let (key, maybe_extra_nibble, _) = match Self::extract_key_from_raw_item(raw_item) {
579 Some(Ok(k)) => k,
580 Some(Err(err)) => return Some(Err(err)),
581 None => continue,
582 };
583
584 if let Some(extra_nibble) = maybe_extra_nibble {
585 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))));
586 }
587
588 return Some(Ok(key));
589 }
590 None
591 }
592
593 fn extract_key_from_raw_item<'a>(
598 raw_item: Result<
599 (&NibbleVec, Option<&TrieHash<L>>, &'a Arc<OwnedNode<DBValue>>),
600 TrieHash<L>,
601 CError<L>,
602 >,
603 ) -> Option<Result<(Vec<u8>, Option<u8>, Value<'a>), TrieHash<L>, CError<L>>> {
604 let (prefix, _, node) = match raw_item {
605 Ok(raw_item) => raw_item,
606 Err(err) => return Some(Err(err)),
607 };
608
609 let mut prefix = prefix.clone();
610 let value = match node.node() {
611 Node::Leaf(partial, value) => {
612 prefix.append_partial(partial.right());
613 value
614 },
615 Node::Branch(_, value) => match value {
616 Some(value) => value,
617 None => return None,
618 },
619 Node::NibbledBranch(partial, _, value) => {
620 prefix.append_partial(partial.right());
621 match value {
622 Some(value) => value,
623 None => return None,
624 }
625 },
626 _ => return None,
627 };
628
629 let (key_slice, maybe_extra_nibble) = prefix.as_prefix();
630
631 Some(Ok((key_slice.to_vec(), maybe_extra_nibble, value)))
632 }
633}
634
635pub struct TrieDBNodeIterator<'a, 'cache, L: TrieLayout> {
641 db: &'a TrieDB<'a, 'cache, L>,
642 raw_iter: TrieDBRawIterator<L>,
643}
644
645impl<'a, 'cache, L: TrieLayout> TrieDBNodeIterator<'a, 'cache, L> {
646 pub fn new(db: &'a TrieDB<'a, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
648 Ok(Self { raw_iter: TrieDBRawIterator::new(db)?, db })
649 }
650
651 pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
653 Self { db, raw_iter }
654 }
655
656 pub fn into_raw(self) -> TrieDBRawIterator<L> {
658 self.raw_iter
659 }
660
661 pub fn fetch_value(
663 &self,
664 key: &[u8],
665 prefix: Prefix,
666 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
667 TrieDBRawIterator::fetch_value(self.db, key, prefix)
668 }
669
670 pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
673 self.raw_iter.prefix(self.db, prefix, true)
674 }
675
676 pub fn prefix_then_seek(
679 &mut self,
680 prefix: &[u8],
681 seek: &[u8],
682 ) -> Result<(), TrieHash<L>, CError<L>> {
683 self.raw_iter.prefix_then_seek(self.db, prefix, seek)
684 }
685
686 pub fn db(&self) -> &dyn hash_db::HashDBRef<L::Hash, DBValue> {
688 self.db.db()
689 }
690}
691
692impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBNodeIterator<'a, 'cache, L> {
693 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
694 self.raw_iter.seek(self.db, key, true).map(|_| ())
695 }
696}
697
698impl<'a, 'cache, L: TrieLayout> Iterator for TrieDBNodeIterator<'a, 'cache, L> {
699 type Item =
700 Result<(NibbleVec, Option<TrieHash<L>>, Arc<OwnedNode<DBValue>>), TrieHash<L>, CError<L>>;
701
702 fn next(&mut self) -> Option<Self::Item> {
703 self.raw_iter.next_raw_item(self.db, true).map(|result| {
704 result.map(|(nibble, hash, node)| (nibble.clone(), hash.cloned(), node.clone()))
705 })
706 }
707}
708
709pub struct TrieDBNodeDoubleEndedIterator<'a, 'cache, L: TrieLayout> {
711 db: &'a TrieDB<'a, 'cache, L>,
712 raw_iter: TrieDBRawIterator<L>,
713 back_raw_iter: TrieDBRawIterator<L>,
714}
715
716impl<'a, 'cache, L: TrieLayout> TrieDBNodeDoubleEndedIterator<'a, 'cache, L> {
717 pub fn new(db: &'a TrieDB<'a, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
719 Ok(Self {
720 db,
721 raw_iter: TrieDBRawIterator::new(db)?,
722 back_raw_iter: TrieDBRawIterator::new(db)?,
723 })
724 }
725
726 pub fn from_raw(
728 db: &'a TrieDB<'a, 'cache, L>,
729 raw_iter: TrieDBRawIterator<L>,
730 back_raw_iter: TrieDBRawIterator<L>,
731 ) -> Self {
732 Self { db, raw_iter, back_raw_iter }
733 }
734
735 pub fn into_raw(self) -> TrieDBRawIterator<L> {
737 self.raw_iter
738 }
739
740 pub fn into_raw_back(self) -> TrieDBRawIterator<L> {
742 self.back_raw_iter
743 }
744
745 pub fn fetch_value(
747 &self,
748 key: &[u8],
749 prefix: Prefix,
750 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
751 TrieDBRawIterator::fetch_value(self.db, key, prefix)
752 }
753
754 pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
757 self.raw_iter.prefix(self.db, prefix, true)?;
758 self.back_raw_iter.prefix(self.db, prefix, false)
759 }
760
761 pub fn prefix_then_seek(
764 &mut self,
765 prefix: &[u8],
766 seek: &[u8],
767 ) -> Result<(), TrieHash<L>, CError<L>> {
768 self.raw_iter.prefix_then_seek(self.db, prefix, seek)?;
769 self.back_raw_iter.prefix_then_seek(self.db, prefix, seek)
770 }
771
772 pub fn db(&self) -> &dyn hash_db::HashDBRef<L::Hash, DBValue> {
774 self.db.db()
775 }
776}
777
778impl<L: TrieLayout> TrieDoubleEndedIterator<L> for TrieDBNodeDoubleEndedIterator<'_, '_, L> {}
779
780impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBNodeDoubleEndedIterator<'a, 'cache, L> {
781 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
782 self.raw_iter.seek(self.db, key, true).map(|_| ())?;
783 self.back_raw_iter.seek(self.db, key, false).map(|_| ())
784 }
785}
786
787impl<'a, 'cache, L: TrieLayout> Iterator for TrieDBNodeDoubleEndedIterator<'a, 'cache, L> {
788 type Item =
789 Result<(NibbleVec, Option<TrieHash<L>>, Arc<OwnedNode<DBValue>>), TrieHash<L>, CError<L>>;
790
791 fn next(&mut self) -> Option<Self::Item> {
792 self.raw_iter.next_raw_item(self.db, true).map(|result| {
793 result.map(|(nibble, hash, node)| (nibble.clone(), hash.cloned(), node.clone()))
794 })
795 }
796}
797
798impl<'a, 'cache, L: TrieLayout> DoubleEndedIterator
799 for TrieDBNodeDoubleEndedIterator<'a, 'cache, L>
800{
801 fn next_back(&mut self) -> Option<Self::Item> {
802 self.back_raw_iter.next_raw_item(self.db, false).map(|result| {
803 result.map(|(nibble, hash, node)| (nibble.clone(), hash.cloned(), node.clone()))
804 })
805 }
806}