use crate::index::Cursor as CursorTrait;
use commonware_runtime::telemetry::metrics::{Counter, Gauge};
use std::ptr::NonNull;
pub struct Record<V: Send + Sync> {
pub(super) value: V,
pub(super) next: Option<Box<Self>>,
}
pub(super) fn insert_front<V: Send + Sync>(record: &mut Record<V>, value: V) {
let old = std::mem::replace(&mut record.value, value);
record.next = Some(Box::new(Record {
value: old,
next: record.next.take(),
}));
}
pub trait IndexEntry<V: Send + Sync>: Send + Sync {
fn get_mut(&mut self) -> &mut Record<V>;
fn remove(self);
}
const MUST_CALL_NEXT: &str = "must call Cursor::next()";
const NO_ACTIVE_ITEM: &str = "no active item in Cursor";
enum State<V: Send + Sync> {
NeedNext { from: Option<NonNull<Record<V>>> },
Active {
current: NonNull<Record<V>>,
prev: Option<NonNull<Record<V>>>,
},
Done { tail: NonNull<Record<V>> },
EntryRemoved,
}
impl<V: Send + Sync> Clone for State<V> {
fn clone(&self) -> Self {
*self
}
}
impl<V: Send + Sync> Copy for State<V> {}
pub struct Cursor<'a, V: Send + Sync, E: IndexEntry<V>> {
entry: Option<E>,
state: State<V>,
keys: &'a Gauge,
items: &'a Gauge,
pruned: &'a Counter,
}
impl<'a, V: Send + Sync, E: IndexEntry<V>> Cursor<'a, V, E> {
pub(super) const fn new(
entry: E,
keys: &'a Gauge,
items: &'a Gauge,
pruned: &'a Counter,
) -> Self {
Self {
entry: Some(entry),
state: State::NeedNext { from: None },
keys,
items,
pruned,
}
}
const fn record_mut(&mut self, mut ptr: NonNull<Record<V>>) -> &mut Record<V> {
unsafe { ptr.as_mut() }
}
}
impl<V: Send + Sync, E: IndexEntry<V>> CursorTrait for Cursor<'_, V, E> {
type Value = V;
fn next(&mut self) -> Option<&V> {
let from = match self.state {
State::Done { .. } | State::EntryRemoved => return None,
State::NeedNext { from } => from,
State::Active { current, .. } => Some(current),
};
let next_ptr = if let Some(from) = from {
match self.record_mut(from).next.as_deref_mut() {
Some(next) => NonNull::from(next),
None => {
self.state = State::Done { tail: from };
return None;
}
}
} else {
NonNull::from(self.entry.as_mut().unwrap().get_mut())
};
self.state = State::Active {
current: next_ptr,
prev: from,
};
Some(&self.record_mut(next_ptr).value)
}
fn update(&mut self, v: V) {
match self.state {
State::NeedNext { .. } => panic!("{MUST_CALL_NEXT}"),
State::Done { .. } | State::EntryRemoved => panic!("{NO_ACTIVE_ITEM}"),
State::Active { current, .. } => {
self.record_mut(current).value = v;
}
}
}
fn insert(&mut self, v: V) {
match self.state {
State::NeedNext { .. } => panic!("{MUST_CALL_NEXT}"),
State::Active { current, .. } => {
self.items.inc();
let inserted = {
let current_record = self.record_mut(current);
let new = Box::new(Record {
value: v,
next: current_record.next.take(),
});
current_record.next = Some(new);
NonNull::from(current_record.next.as_deref_mut().unwrap())
};
self.state = State::NeedNext {
from: Some(inserted),
};
}
State::EntryRemoved => {
self.items.inc();
let entry_record = self.entry.as_mut().unwrap().get_mut();
entry_record.value = v;
entry_record.next = None;
self.state = State::Done {
tail: NonNull::from(entry_record),
};
}
State::Done { tail } => {
self.items.inc();
let inserted = {
let tail_record = self.record_mut(tail);
tail_record.next = Some(Box::new(Record {
value: v,
next: None,
}));
NonNull::from(tail_record.next.as_deref_mut().unwrap())
};
self.state = State::Done { tail: inserted };
}
}
}
fn delete(&mut self) {
let (current, prev) = match self.state {
State::NeedNext { .. } => panic!("{MUST_CALL_NEXT}"),
State::Done { .. } | State::EntryRemoved => panic!("{NO_ACTIVE_ITEM}"),
State::Active { current, prev } => (current, prev),
};
self.pruned.inc();
self.items.dec();
if let Some(prev) = prev {
let next = self.record_mut(current).next.take();
self.record_mut(prev).next = next;
self.state = State::NeedNext { from: Some(prev) };
} else {
let head = self.record_mut(current);
if let Some(next) = head.next.take() {
head.value = next.value;
head.next = next.next;
self.state = State::NeedNext { from: None };
} else {
self.state = State::EntryRemoved;
}
}
}
}
unsafe impl<V: Send + Sync, E: IndexEntry<V>> Send for Cursor<'_, V, E> {}
unsafe impl<V: Send + Sync, E: IndexEntry<V>> Sync for Cursor<'_, V, E> {}
impl<V: Send + Sync, E: IndexEntry<V>> Drop for Cursor<'_, V, E> {
fn drop(&mut self) {
if matches!(self.state, State::EntryRemoved) {
self.keys.dec();
self.entry.take().unwrap().remove();
}
}
}
pub struct ImmutableCursor<'a, V: Send + Sync> {
current: Option<&'a Record<V>>,
}
impl<'a, V: Send + Sync> ImmutableCursor<'a, V> {
pub(super) const fn new(record: &'a Record<V>) -> Self {
Self {
current: Some(record),
}
}
}
impl<'a, V: Send + Sync> Iterator for ImmutableCursor<'a, V> {
type Item = &'a V;
fn next(&mut self) -> Option<Self::Item> {
self.current.map(|record| {
let value = &record.value;
self.current = record.next.as_deref();
value
})
}
}