diff --git a/src/database/stream.rs b/src/database/stream.rs index eeb7d6c3..af86a6bd 100644 --- a/src/database/stream.rs +++ b/src/database/stream.rs @@ -25,6 +25,10 @@ pub(crate) struct State<'a> { pub(crate) trait Cursor<'a, T>: Send { fn state(&self) -> &State<'a>; + fn state_mut(&mut self) -> &mut State<'a>; + + fn count(&self) -> (usize, Option); + fn fetch(&self) -> Option; fn seek(&mut self); @@ -111,9 +115,15 @@ impl<'a> State<'a> { } } - pub(super) fn is_incomplete(&self) -> bool { - matches!(self.status(), Some(e) if is_incomplete(&e)) - } + #[inline] + #[expect(clippy::unused_self)] + #[tracing::instrument(level = "trace", skip_all, ret)] + pub(super) fn count_fwd(&self) -> (usize, Option) { (0, None) } + + #[inline] + #[expect(clippy::unused_self)] + #[tracing::instrument(level = "trace", skip_all, ret)] + pub(super) fn count_rev(&self) -> (usize, Option) { (0, None) } #[inline] fn fetch_key(&self) -> Option> { self.inner.key() } @@ -124,6 +134,10 @@ impl<'a> State<'a> { #[inline] fn fetch(&self) -> Option> { self.inner.item() } + pub(super) fn is_incomplete(&self) -> bool { + matches!(self.status(), Some(e) if is_incomplete(&e)) + } + #[inline] pub(super) fn status(&self) -> Option { self.inner.status().err() } diff --git a/src/database/stream/items.rs b/src/database/stream/items.rs index 9180d582..cd5a65b7 100644 --- a/src/database/stream/items.rs +++ b/src/database/stream/items.rs @@ -24,10 +24,16 @@ impl<'a> Cursor<'a, KeyVal<'a>> for Items<'a> { fn state(&self) -> &State<'a> { &self.state } #[inline] - fn fetch(&self) -> Option> { self.state.fetch().map(keyval_longevity) } + fn state_mut(&mut self) -> &mut State<'a> { &mut self.state } #[inline] - fn seek(&mut self) { self.state.seek_fwd(); } + fn count(&self) -> (usize, Option) { self.state().count_fwd() } + + #[inline] + fn fetch(&self) -> Option> { self.state().fetch().map(keyval_longevity) } + + #[inline] + fn seek(&mut self) { self.state_mut().seek_fwd(); } } impl<'a> Stream for Items<'a> { @@ -36,9 +42,11 @@ impl<'a> Stream for Items<'a> { fn poll_next(mut self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll> { Poll::Ready(self.seek_and_get()) } + + fn size_hint(&self) -> (usize, Option) { self.count() } } impl FusedStream for Items<'_> { #[inline] - fn is_terminated(&self) -> bool { !self.state.init && !self.state.valid() } + fn is_terminated(&self) -> bool { !self.state().init && !self.state().valid() } } diff --git a/src/database/stream/items_rev.rs b/src/database/stream/items_rev.rs index ae5b9fbd..0c842699 100644 --- a/src/database/stream/items_rev.rs +++ b/src/database/stream/items_rev.rs @@ -24,10 +24,16 @@ impl<'a> Cursor<'a, KeyVal<'a>> for ItemsRev<'a> { fn state(&self) -> &State<'a> { &self.state } #[inline] - fn fetch(&self) -> Option> { self.state.fetch().map(keyval_longevity) } + fn state_mut(&mut self) -> &mut State<'a> { &mut self.state } #[inline] - fn seek(&mut self) { self.state.seek_rev(); } + fn count(&self) -> (usize, Option) { self.state().count_rev() } + + #[inline] + fn fetch(&self) -> Option> { self.state().fetch().map(keyval_longevity) } + + #[inline] + fn seek(&mut self) { self.state_mut().seek_rev(); } } impl<'a> Stream for ItemsRev<'a> { @@ -36,9 +42,11 @@ impl<'a> Stream for ItemsRev<'a> { fn poll_next(mut self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll> { Poll::Ready(self.seek_and_get()) } + + fn size_hint(&self) -> (usize, Option) { self.count() } } impl FusedStream for ItemsRev<'_> { #[inline] - fn is_terminated(&self) -> bool { !self.state.init && !self.state.valid() } + fn is_terminated(&self) -> bool { !self.state().init && !self.state().valid() } } diff --git a/src/database/stream/keys.rs b/src/database/stream/keys.rs index e0257934..d4703610 100644 --- a/src/database/stream/keys.rs +++ b/src/database/stream/keys.rs @@ -24,10 +24,16 @@ impl<'a> Cursor<'a, Key<'a>> for Keys<'a> { fn state(&self) -> &State<'a> { &self.state } #[inline] - fn fetch(&self) -> Option> { self.state.fetch_key().map(slice_longevity) } + fn state_mut(&mut self) -> &mut State<'a> { &mut self.state } #[inline] - fn seek(&mut self) { self.state.seek_fwd(); } + fn count(&self) -> (usize, Option) { self.state().count_fwd() } + + #[inline] + fn fetch(&self) -> Option> { self.state().fetch_key().map(slice_longevity) } + + #[inline] + fn seek(&mut self) { self.state_mut().seek_fwd(); } } impl<'a> Stream for Keys<'a> { @@ -36,9 +42,11 @@ impl<'a> Stream for Keys<'a> { fn poll_next(mut self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll> { Poll::Ready(self.seek_and_get()) } + + fn size_hint(&self) -> (usize, Option) { self.count() } } impl FusedStream for Keys<'_> { #[inline] - fn is_terminated(&self) -> bool { !self.state.init && !self.state.valid() } + fn is_terminated(&self) -> bool { !self.state().init && !self.state().valid() } } diff --git a/src/database/stream/keys_rev.rs b/src/database/stream/keys_rev.rs index a6007b38..480e6907 100644 --- a/src/database/stream/keys_rev.rs +++ b/src/database/stream/keys_rev.rs @@ -24,10 +24,16 @@ impl<'a> Cursor<'a, Key<'a>> for KeysRev<'a> { fn state(&self) -> &State<'a> { &self.state } #[inline] - fn fetch(&self) -> Option> { self.state.fetch_key().map(slice_longevity) } + fn state_mut(&mut self) -> &mut State<'a> { &mut self.state } #[inline] - fn seek(&mut self) { self.state.seek_rev(); } + fn count(&self) -> (usize, Option) { self.state().count_rev() } + + #[inline] + fn fetch(&self) -> Option> { self.state().fetch_key().map(slice_longevity) } + + #[inline] + fn seek(&mut self) { self.state_mut().seek_rev(); } } impl<'a> Stream for KeysRev<'a> { @@ -36,9 +42,11 @@ impl<'a> Stream for KeysRev<'a> { fn poll_next(mut self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll> { Poll::Ready(self.seek_and_get()) } + + fn size_hint(&self) -> (usize, Option) { self.count() } } impl FusedStream for KeysRev<'_> { #[inline] - fn is_terminated(&self) -> bool { !self.state.init && !self.state.valid() } + fn is_terminated(&self) -> bool { !self.state().init && !self.state().valid() } }