Skip to main content

tuwunel_database/stream/
keys.rs

1use std::pin::Pin;
2
3use futures::{
4	Stream,
5	stream::FusedStream,
6	task::{Context, Poll},
7};
8use tuwunel_core::Result;
9
10use super::{Cursor, State, slice_longevity};
11use crate::keyval::Key;
12
13/// Streams keys in ascending RocksDB order.
14///
15/// The first poll uses a prepared position or seeks to the first key, while
16/// later polls advance before fetching. The slice borrows cursor storage and
17/// remains valid only until the next cursor movement.
18pub(crate) struct Keys<'a> {
19	state: State<'a>,
20}
21
22impl<'a> From<State<'a>> for Keys<'a> {
23	#[inline]
24	fn from(state: State<'a>) -> Self { Self { state } }
25}
26
27impl<'a> Cursor<'a, Key<'a>> for Keys<'a> {
28	#[inline]
29	fn state(&self) -> &State<'a> { &self.state }
30
31	#[inline]
32	fn state_mut(&mut self) -> &mut State<'a> { &mut self.state }
33
34	#[inline]
35	fn count(&self) -> (usize, Option<usize>) { self.state().count_fwd() }
36
37	#[inline]
38	fn fetch(&self) -> Option<Key<'a>> { self.state().fetch_key().map(slice_longevity) }
39
40	#[inline]
41	fn seek(&mut self) { self.state_mut().seek_fwd(); }
42}
43
44impl<'a> Stream for Keys<'a> {
45	type Item = Result<Key<'a>>;
46
47	fn poll_next(mut self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
48		Poll::Ready(self.seek_and_get())
49	}
50
51	fn size_hint(&self) -> (usize, Option<usize>) { self.count() }
52}
53
54impl FusedStream for Keys<'_> {
55	#[inline]
56	fn is_terminated(&self) -> bool { !self.state().init && !self.state().valid() }
57}