Skip to main content

trie_db/
iterator.rs

1// Copyright 2017, 2021 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 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	/// Move on to the next status in the node's sequence in a direction.
46	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
72/// Iterator for going through all nodes in the trie in pre-order traversal order.
73pub struct TrieDBRawIterator<L: TrieLayout> {
74	/// Forward trail of nodes to visit.
75	trail: Vec<Crumb<L::Hash>>,
76	/// Forward iteration key nibbles of the current node.
77	key_nibbles: NibbleVec,
78}
79
80impl<L: TrieLayout> TrieDBRawIterator<L> {
81	/// Create a new empty iterator.
82	pub fn empty() -> Self {
83		Self { trail: Vec::new(), key_nibbles: NibbleVec::new() }
84	}
85
86	/// Create a new iterator.
87	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	/// Create a new iterator, but limited to a given prefix.
102	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	/// Create a new iterator, but limited to a given prefix.
110	/// It then do a seek operation from prefixed context (using `seek` lose
111	/// prefix context by default).
112	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	/// Descend into a node.
123	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	/// Skip the descendants of the node most recently yielded by `next_raw_item`: iteration
129	/// continues with the node's next sibling (or an ancestor's).
130	///
131	/// Must only be called directly after `next_raw_item(_, true)` yielded a node.
132	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	/// Fetch value by hash at a current node height
139	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	/// Seek a node position at 'key' for iterator.
150	/// Returns true if the cursor is at or after the key, but still shares
151	/// a common prefix with the key, return false if the key do not
152	/// share its prefix with the node.
153	/// This indicates if there is still nodes to iterate over in the case
154	/// where we limit iteration to 'key' as a prefix.
155	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
291	/// or returned after this operation.
292	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
311	/// or returned after this operation.
312	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			// There's no prefix, so just seek.
320			return self.seek(db, seek, true).map(|_| ());
321		}
322
323		if seek.is_empty() || seek <= prefix {
324			// Either we're not supposed to seek anywhere,
325			// or we're supposed to seek *before* the prefix,
326			// so just directly go to the prefix.
327			return self.prefix(db, prefix, true);
328		}
329
330		if !seek.starts_with(prefix) {
331			// We're supposed to seek *after* the prefix,
332			// so just return an empty iterator.
333			self.trail.clear();
334			return Ok(());
335		}
336
337		if !self.seek(db, prefix, true)? {
338			// The database doesn't have a key with such a prefix.
339			self.trail.clear();
340			return Ok(());
341		}
342
343		// Now seek forward again.
344		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		// look first prefix in trail
349		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	/// Fetches the next raw item.
377	//
378	/// Must be called with the same `db` as when the iterator was created.
379	///
380	/// Specify `fwd` to indicate the direction of the iteration (`true` for forward).
381	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	/// Fetches the next trie item.
498	///
499	/// Must be called with the same `db` as when the iterator was created.
500	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	/// Fetches the previous trie item.
526	///
527	/// Must be called with the same `db` as when the iterator was created.
528	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	/// Fetches the next key.
554	///
555	/// Must be called with the same `db` as when the iterator was created.
556	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	/// Fetches the previous key.
574	///
575	/// Must be called with the same `db` as when the iterator was created.
576	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	/// Extracts the key from the result of a raw item retrieval.
594	///
595	/// Given a raw item, it extracts the key information, including the key bytes, an optional
596	/// extra nibble (prefix padding), and the node value.
597	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
635/// Iterator for going through all nodes in the trie in pre-order traversal order.
636///
637/// You can reduce the number of iterations and simultaneously iterate in both directions with two
638/// cursors by using `TrieDBNodeDoubleEndedIterator`. You can convert this iterator into a double
639/// ended iterator with `into_double_ended_iter`.
640pub 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	/// Create a new iterator.
647	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	/// Restore an iterator from a raw iterator.
652	pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
653		Self { db, raw_iter }
654	}
655
656	/// Convert the iterator to a raw iterator.
657	pub fn into_raw(self) -> TrieDBRawIterator<L> {
658		self.raw_iter
659	}
660
661	/// Fetch value by hash at a current node height
662	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
671	/// or returned after this operation.
672	pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
673		self.raw_iter.prefix(self.db, prefix, true)
674	}
675
676	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
677	/// or returned after this operation.
678	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	/// Access inner hash db.
687	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
709/// Double ended iterator for going through all nodes in the trie in pre-order traversal order.
710pub 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	/// Create a new double ended iterator.
718	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	/// Restore an iterator from a raw iterators.
727	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	/// Convert the iterator to a raw forward iterator.
736	pub fn into_raw(self) -> TrieDBRawIterator<L> {
737		self.raw_iter
738	}
739
740	/// Convert the iterator to a raw backward iterator.
741	pub fn into_raw_back(self) -> TrieDBRawIterator<L> {
742		self.back_raw_iter
743	}
744
745	/// Fetch value by hash at a current node height
746	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
755	/// or returned after this operation.
756	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
762	/// or returned after this operation.
763	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	/// Access inner hash db.
773	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}