1use std::fmt;
5
6use firewood::api::{self, ArcDynDbView, BoxKeyValueIter};
7use firewood::merkle;
8use firewood_metrics::MetricsContext;
9use std::iter::FusedIterator;
10
11type KeyValueItem = (merkle::Key, merkle::Value);
12
13#[derive(Default)]
17pub struct IteratorHandle<'view> {
18 iter: Option<BoxKeyValueIter<'view>>,
19 view: Option<ArcDynDbView>,
20 metrics_context: Option<MetricsContext>,
21}
22
23impl fmt::Debug for IteratorHandle<'_> {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 f.debug_struct("IteratorHandle")
26 .field("metrics_context", &self.metrics_context)
27 .finish_non_exhaustive()
28 }
29}
30
31impl<'view> IteratorHandle<'view> {
32 #[must_use]
33 pub(crate) fn new(
34 view: ArcDynDbView,
35 iter: BoxKeyValueIter<'view>,
36 metrics_context: Option<MetricsContext>,
37 ) -> Self {
38 Self {
39 iter: Some(iter),
40 view: Some(view),
41 metrics_context,
42 }
43 }
44}
45
46impl Iterator for IteratorHandle<'_> {
47 type Item = Result<KeyValueItem, api::Error>;
48
49 fn next(&mut self) -> Option<Self::Item> {
50 let out = self.iter.as_mut()?.next();
51 if out.is_none() {
52 self.iter = None;
54 self.view = None;
55 }
56 out.map(|res| res.map_err(api::Error::from))
57 }
58}
59
60impl FusedIterator for IteratorHandle<'_> {}
61
62#[expect(clippy::missing_errors_doc)]
63impl IteratorHandle<'_> {
64 pub fn iter_next_n(&mut self, n: usize) -> Result<Vec<KeyValueItem>, api::Error> {
65 self.by_ref().take(n).collect()
66 }
67}
68
69#[derive(Debug, Default)]
70pub struct CreateIteratorResult<'db>(pub IteratorHandle<'db>);
71
72impl crate::MetricsContextExt for IteratorHandle<'_> {
73 fn metrics_context(&self) -> Option<MetricsContext> {
74 self.metrics_context
75 }
76}