#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
use std::fmt;
use self::{config::ConfigPrivate, control::PageControl, key::PageNo, page::Page};
mod config;
mod control;
mod handles;
mod key;
mod loom;
mod page;
mod slot;
pub use self::{
config::{Config, DefaultConfig},
handles::{BorrowedEntry, Iter, OwnedEntry, VacantEntry},
key::Key,
};
pub struct Idr<T, C = DefaultConfig> {
pages: Box<[Page<T, C>]>,
page_control: PageControl,
}
impl<T: 'static> Default for Idr<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: 'static, C: Config> Idr<T, C> {
pub const USED_BITS: u32 = C::USED_BITS;
pub fn new() -> Self {
assert!(C::ENSURE_VALID);
Self {
pages: (0..C::MAX_PAGES).map(PageNo::new).map(Page::new).collect(),
page_control: PageControl::default(),
}
}
#[inline]
pub fn insert(&self, value: T) -> Option<Key> {
self.vacant_entry().map(|entry| {
let key = entry.key();
entry.insert(value);
key
})
}
#[inline]
pub fn vacant_entry(&self) -> Option<VacantEntry<'_, T, C>> {
self.page_control.choose(&self.pages, |page| {
page.reserve(&self.page_control)
.map(|(key, slot)| VacantEntry::new(page, slot, key))
})
}
#[inline]
pub fn remove(&self, key: Key) -> bool {
let page_no = key.page_no::<C>();
self.pages
.get(page_no.to_usize())
.is_some_and(|page| page.remove(key))
}
#[inline]
pub fn get<'g>(&self, key: Key, guard: &'g EbrGuard) -> Option<BorrowedEntry<'g, T>> {
let page_no = key.page_no::<C>();
let page = self.pages.get(page_no.to_usize())?;
page.get(key, guard)
}
#[inline]
pub fn get_owned(&self, key: Key) -> Option<OwnedEntry<T>> {
self.get(key, &EbrGuard::new())?.to_owned()
}
#[inline]
pub fn contains(&self, key: Key) -> bool {
self.get(key, &EbrGuard::new()).is_some()
}
#[inline]
pub fn iter<'g>(&self, guard: &'g EbrGuard) -> Iter<'g, '_, T, C> {
Iter::new(&self.pages, guard)
}
}
impl<T, C: Config> fmt::Debug for Idr<T, C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Idr")
.field("allocated_pages", &self.page_control.allocated())
.field("config", &C::debug())
.finish_non_exhaustive()
}
}
#[derive(Default)]
#[must_use]
pub struct EbrGuard(sdd::Guard);
impl EbrGuard {
#[inline]
pub fn new() -> Self {
Self(sdd::Guard::new())
}
}
impl fmt::Debug for EbrGuard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EbrGuard").finish()
}
}