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	/// Fetch value by hash at a current node height
129	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	/// Seek a node position at 'key' for iterator.
140	/// Returns true if the cursor is at or after the key, but still shares
141	/// a common prefix with the key, return false if the key do not
142	/// share its prefix with the node.
143	/// This indicates if there is still nodes to iterate over in the case
144	/// where we limit iteration to 'key' as a prefix.
145	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
281	/// or returned after this operation.
282	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
301	/// or returned after this operation.
302	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			// There's no prefix, so just seek.
310			return self.seek(db, seek, true).map(|_| ());
311		}
312
313		if seek.is_empty() || seek <= prefix {
314			// Either we're not supposed to seek anywhere,
315			// or we're supposed to seek *before* the prefix,
316			// so just directly go to the prefix.
317			return self.prefix(db, prefix, true);
318		}
319
320		if !seek.starts_with(prefix) {
321			// We're supposed to seek *after* the prefix,
322			// so just return an empty iterator.
323			self.trail.clear();
324			return Ok(());
325		}
326
327		if !self.seek(db, prefix, true)? {
328			// The database doesn't have a key with such a prefix.
329			self.trail.clear();
330			return Ok(());
331		}
332
333		// Now seek forward again.
334		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		// look first prefix in trail
339		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	/// Fetches the next raw item.
367	//
368	/// Must be called with the same `db` as when the iterator was created.
369	///
370	/// Specify `fwd` to indicate the direction of the iteration (`true` for forward).
371	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	/// Fetches the next trie item.
488	///
489	/// Must be called with the same `db` as when the iterator was created.
490	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	/// Fetches the previous trie item.
516	///
517	/// Must be called with the same `db` as when the iterator was created.
518	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	/// Fetches the next key.
544	///
545	/// Must be called with the same `db` as when the iterator was created.
546	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	/// Fetches the previous key.
564	///
565	/// Must be called with the same `db` as when the iterator was created.
566	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	/// Extracts the key from the result of a raw item retrieval.
584	///
585	/// Given a raw item, it extracts the key information, including the key bytes, an optional
586	/// extra nibble (prefix padding), and the node value.
587	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
625/// Iterator for going through all nodes in the trie in pre-order traversal order.
626///
627/// You can reduce the number of iterations and simultaneously iterate in both directions with two
628/// cursors by using `TrieDBNodeDoubleEndedIterator`. You can convert this iterator into a double
629/// ended iterator with `into_double_ended_iter`.
630pub 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	/// Create a new iterator.
637	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	/// Restore an iterator from a raw iterator.
642	pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
643		Self { db, raw_iter }
644	}
645
646	/// Convert the iterator to a raw iterator.
647	pub fn into_raw(self) -> TrieDBRawIterator<L> {
648		self.raw_iter
649	}
650
651	/// Fetch value by hash at a current node height
652	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
661	/// or returned after this operation.
662	pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
663		self.raw_iter.prefix(self.db, prefix, true)
664	}
665
666	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
667	/// or returned after this operation.
668	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	/// Access inner hash db.
677	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
699/// Double ended iterator for going through all nodes in the trie in pre-order traversal order.
700pub 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	/// Create a new double ended iterator.
708	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	/// Restore an iterator from a raw iterators.
717	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	/// Convert the iterator to a raw forward iterator.
726	pub fn into_raw(self) -> TrieDBRawIterator<L> {
727		self.raw_iter
728	}
729
730	/// Convert the iterator to a raw backward iterator.
731	pub fn into_raw_back(self) -> TrieDBRawIterator<L> {
732		self.back_raw_iter
733	}
734
735	/// Fetch value by hash at a current node height
736	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
745	/// or returned after this operation.
746	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
752	/// or returned after this operation.
753	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	/// Access inner hash db.
763	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}