Skip to main content

arctic/raw/
iter.rs

1mod postorder;
2pub(crate) mod range;
3
4pub(crate) use postorder::PostorderIter;
5pub use range::Range;
6pub(crate) use range::RangeIter;
7pub(crate) use range::Unbound;
8
9use core::ops::ControlFlow;
10use core::ptr::NonNull;
11
12use crate::raw::Edge;
13use crate::raw::Key;
14use crate::raw::key;
15use crate::sync::Atomic;
16
17/// Key order for scan operations (e.g., [`concurrent::Shard::entries`][crate::concurrent::Shard::entries]).
18///
19/// Iterators in this crate do not implement [`core::iter::DoubleEndedIterator`]
20/// because it would require maintaining two traversal stacks at runtime
21/// (for tracking the lower and upper bound).
22#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
23pub enum Order {
24    /// Ascending key order.
25    #[default]
26    Ascend,
27
28    /// Descending key order.
29    Descend,
30}
31
32pub(crate) struct EntryIter<'g, 'k, K: Key, R: Range<K::Read<'k>>>(
33    pub(super) RangeIter<'g, K::Read<'k>, K::Write, R>,
34);
35
36impl<'g, 'k, K, R> EntryIter<'g, 'k, K, R>
37where
38    K: Key,
39    R: Range<K::Read<'k>>,
40{
41    #[inline]
42    #[expect(clippy::type_complexity)]
43    pub(crate) fn lend(&mut self) -> Option<(K::Insert<'_>, u64, NonNull<Atomic<Edge<K::Edge>>>)> {
44        self.0
45            .lend()
46            .map(|(writer, value, edge)| (unsafe { K::write_as_insert(writer) }, value, edge))
47    }
48
49    #[inline]
50    pub(crate) fn try_fold<F, B, C>(self, init: C, mut apply: F) -> ControlFlow<B, C>
51    where
52        F: FnMut(C, (K::Insert<'_>, u64, NonNull<Atomic<Edge<K::Edge>>>)) -> ControlFlow<B, C>,
53    {
54        self.0.try_fold(init, |acc, (writer, value, edge)| {
55            apply(acc, (unsafe { K::write_as_insert(writer) }, value, edge))
56        })
57    }
58}
59
60/// Iterator over raw values only
61pub(crate) struct ValueIter<'g, 'k, K: Key, R: Range<K::Read<'k>>>(
62    pub(super) RangeIter<'g, K::Read<'k>, key::Discard<K::Read<'k>>, R>,
63);
64
65impl<'g, 'k, K, R> ValueIter<'g, 'k, K, R>
66where
67    K: Key,
68    R: Range<K::Read<'k>>,
69{
70    #[inline]
71    #[expect(clippy::type_complexity)]
72    pub(crate) fn lend(&mut self) -> Option<(u64, NonNull<Atomic<Edge<K::Edge>>>)> {
73        self.0.lend().map(|(_, value, edge)| (value, edge))
74    }
75
76    #[inline]
77    pub(crate) fn try_fold<F, B, C>(self, init: C, mut apply: F) -> ControlFlow<B, C>
78    where
79        F: FnMut(C, (u64, NonNull<Atomic<Edge<K::Edge>>>)) -> ControlFlow<B, C>,
80    {
81        self.0
82            .try_fold(init, |acc, (_, value, edge)| apply(acc, (value, edge)))
83    }
84}