use std::{marker, mem};
use crate::{alloc, base::marker::ThreadBound, depot::map};
pub mod errors;
pub type Entry<'a, V> =
map::Entry<map::Found<&'a mut Table<V>>, map::Vacancy<&'a mut Table<V>, u64>>;
pub struct Table<V> {
pub(in crate::depot::map::flat) table: map::raw::Table<V>,
pub(in crate::depot::map::flat) len: u32,
pub(in crate::depot::map::flat) shape: map::raw::Shape<V>,
thread: marker::PhantomData<ThreadBound>,
}
impl<V> Table<V> {
pub fn insert<C>(
source: crate::depot::raw::Proof<(&mut Self, C), raw::Available>,
hash: u64,
value: V,
) -> (&mut V, C) {
let (table, context) = source.into_inner();
let entry = unsafe { map::raw::Probe::vacant(table, hash) };
(entry.insert(value), context)
}
pub fn admit<C>(
source: crate::depot::raw::Proof<(&mut Self, C), raw::Available>,
hash: u64,
matches: impl Fn(&V) -> bool,
) -> (Entry<'_, V>, C) {
let (table, context) = source.into_inner();
let entry = unsafe { map::raw::Probe::spare(table, hash, matches) };
(entry, context)
}
pub fn member<C, F: Fn(&V) -> bool>(
source: crate::depot::raw::Proof<(&mut Self, C, u64, F), raw::Member>,
) -> (map::Found<&mut Self>, C) {
let (table, context, hash, matches) = source.into_inner();
(
unsafe { map::raw::Probe::member(table, hash, matches) },
context,
)
}
pub fn try_new(plan: map::Plan) -> Result<Self, alloc::Error> {
let layout = map::raw::Layout::try_plan(plan)?;
let shape = layout.shape();
let table = map::raw::Table::try_new(layout)?;
Ok(Self {
table,
len: 0,
shape,
thread: marker::PhantomData,
})
}
pub fn get(&self, hash: u64, matches: impl Fn(&V) -> bool) -> Option<&V> {
map::raw::Probe::find(self, hash, matches)
}
pub fn get_mut(&mut self, hash: u64, matches: impl Fn(&V) -> bool) -> Option<&mut V> {
Some(self.occupied(hash, matches)?.into_mut())
}
pub fn entry(&mut self, hash: u64, matches: impl Fn(&V) -> bool) -> Option<Entry<'_, V>> {
match map::raw::Probe::new(self, hash, matches).entry() {
map::Entry::Occupied(occupied) => Some(Entry::Occupied(occupied)),
map::Entry::Vacant(vacant) => vacant.map(Entry::Vacant),
}
}
pub fn occupied(
&mut self,
hash: u64,
matches: impl Fn(&V) -> bool,
) -> Option<map::Found<&mut Table<V>>> {
map::raw::Probe::find(self, hash, matches)
}
pub fn try_insert(
&mut self,
hash: u64,
value: V,
matches: impl Fn(&V) -> bool,
) -> Result<(), errors::Insert<V>> {
match map::raw::Probe::reserve(self, hash, matches) {
map::Entry::Occupied(()) => Err(errors::Insert::Occupied(value)),
map::Entry::Vacant(None) => Err(errors::Insert::Full(value)),
map::Entry::Vacant(Some(vacant)) => {
vacant.insert(value);
Ok(())
}
}
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
pub const fn len(&self) -> usize {
self.len as usize
}
pub fn remove(&mut self, hash: u64, matches: impl Fn(&V) -> bool) -> Option<V> {
Some(self.occupied(hash, matches)?.remove())
}
pub fn retire(&mut self, hash: u64, matches: impl Fn(&V) -> bool) {
if let Some(occupied) = self.occupied(hash, matches) {
occupied.discard();
}
}
pub fn values(&self) -> impl Iterator<Item = &V> + '_ {
self.table.values()
}
pub fn clear(&mut self) {
if self.is_empty() {
return;
}
self.table.clear();
self.len = 0;
}
}
unsafe impl<'a, V> map::raw::Query for &'a Table<V> {
const SPARE: bool = true;
type Payload = V;
type Value = V;
type Occupied = &'a V;
fn table(&self) -> &map::raw::Table<V> {
&self.table
}
fn value(entry: map::Found<&Self>) -> &V {
entry.payload()
}
fn occupied(entry: map::Found<Self>) -> Self::Occupied {
let (owner, bucket) = entry.into_parts();
unsafe { owner.table.payload(&bucket) }
}
}
unsafe impl<'a, V> map::raw::Query for &'a mut Table<V> {
const SPARE: bool = true;
type Payload = V;
type Value = V;
type Occupied = map::Found<&'a mut Table<V>>;
fn table(&self) -> &map::raw::Table<V> {
&self.table
}
fn value(entry: map::Found<&Self>) -> &V {
entry.payload()
}
fn occupied(entry: map::Found<Self>) -> Self::Occupied {
entry
}
}
unsafe impl<'a, V> map::raw::Insertion for &'a mut Table<V> {
type Vacant = map::Vacancy<&'a mut Table<V>, u64>;
fn vacant(entry: map::Vacancy<Self>, hash: u64) -> Option<Self::Vacant> {
Self::Vacant::new(entry, hash)
}
}
impl<V> Drop for Table<V> {
fn drop(&mut self) {
let layout = self.shape.layout();
let pointer = self.table.base();
if mem::needs_drop::<V>() {
self.clear();
}
unsafe { layout.bundle().deallocate(pointer) };
}
}
const _: () = {
assert!(mem::size_of::<Table<()>>() == 5 * mem::size_of::<usize>());
assert!(mem::align_of::<Table<()>>() == mem::align_of::<usize>());
assert!(mem::size_of::<Option<Table<()>>>() == mem::size_of::<Table<()>>());
assert!(mem::size_of::<map::raw::Probe<&mut Table<u64>>>() == 3 * mem::size_of::<usize>());
assert!(mem::size_of::<map::Found<&mut Table<u64>>>() == 2 * mem::size_of::<usize>());
assert!(mem::size_of::<map::Vacancy<&mut Table<u64>, u64>>() == 3 * mem::size_of::<usize>());
};
impl<'a, V> map::Found<&'a mut Table<V>> {
pub fn into_mut(self) -> &'a mut V {
value(self)
}
}
impl<V> map::Found<&mut Table<V>> {
pub fn get(&self) -> &V {
self.read().payload()
}
pub fn get_mut(&mut self) -> &mut V {
value(self.reborrow())
}
pub fn remove(self) -> V {
let (map, bucket) = self.into_parts();
map.len -= 1;
unsafe { map::raw::Hole::remove(map, bucket) }
}
pub fn discard(self) {
drop(self.remove());
}
}
impl<'a, V> map::Vacancy<&'a mut Table<V>, u64> {
pub(in crate::depot::map::flat) fn new(
entry: map::Vacancy<&'a mut Table<V>>,
hash: u64,
) -> Option<Self> {
let map = entry.source();
if map.len as usize >= map.shape.capacity().get() {
return None;
}
Some(entry.with_phase(hash))
}
pub fn insert(self, value: V) -> &'a mut V {
let (map, bucket, hash) = self.into_parts();
let value = unsafe { map.table.insert(bucket, hash, value) };
map.len += 1;
value
}
}
fn value<V>(entry: map::Found<&mut Table<V>>) -> &mut V {
let (map, bucket) = entry.into_parts();
unsafe { map.table.payload_mut(&bucket) }
}
pub mod raw;