use crate::{inner::Inner, values::Values, Aliased};
use left_right::ReadGuard;
use std::borrow::Borrow;
use std::collections::hash_map::RandomState;
use std::fmt;
use std::hash::{BuildHasher, Hash};
use std::iter::FromIterator;
mod read_ref;
pub use read_ref::{MapReadRef, ReadGuardIter};
mod factory;
pub use factory::ReadHandleFactory;
pub struct ReadHandle<K, V, M = (), S = RandomState>
where
K: Eq + Hash,
S: BuildHasher,
{
pub(crate) handle: left_right::ReadHandle<Inner<K, V, M, S>>,
}
impl<K, V, M, S> fmt::Debug for ReadHandle<K, V, M, S>
where
K: Eq + Hash + fmt::Debug,
S: BuildHasher,
M: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ReadHandle")
.field("handle", &self.handle)
.finish()
}
}
impl<K, V, M, S> Clone for ReadHandle<K, V, M, S>
where
K: Eq + Hash,
S: BuildHasher,
{
fn clone(&self) -> Self {
Self {
handle: self.handle.clone(),
}
}
}
impl<K, V, M, S> ReadHandle<K, V, M, S>
where
K: Eq + Hash,
S: BuildHasher,
{
pub(crate) fn new(handle: left_right::ReadHandle<Inner<K, V, M, S>>) -> Self {
Self { handle }
}
}
impl<K, V, M, S> ReadHandle<K, V, M, S>
where
K: Eq + Hash,
V: Eq + Hash,
S: BuildHasher,
M: Clone,
{
pub fn enter(&self) -> Option<MapReadRef<'_, K, V, M, S>> {
let guard = self.handle.enter()?;
if !guard.ready {
return None;
}
Some(MapReadRef { guard })
}
pub fn len(&self) -> usize {
self.enter().map_or(0, |x| x.len())
}
pub fn is_empty(&self) -> bool {
self.enter().map_or(true, |x| x.is_empty())
}
pub fn meta(&self) -> Option<ReadGuard<'_, M>> {
Some(ReadGuard::map(self.handle.enter()?, |inner| &inner.meta))
}
fn get_raw<Q: ?Sized>(&self, key: &Q) -> Option<ReadGuard<'_, Values<V, S>>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let inner = self.handle.enter()?;
if !inner.ready {
return None;
}
ReadGuard::try_map(inner, |inner| inner.data.get(key).map(AsRef::as_ref))
}
#[inline]
pub fn get<'rh, Q: ?Sized>(&'rh self, key: &'_ Q) -> Option<ReadGuard<'rh, Values<V, S>>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.get_raw(key.borrow())
}
#[inline]
pub fn get_one<'rh, Q: ?Sized>(&'rh self, key: &'_ Q) -> Option<ReadGuard<'rh, V>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
ReadGuard::try_map(self.get_raw(key.borrow())?, |x| x.get_one())
}
pub fn meta_get<Q: ?Sized>(&self, key: &Q) -> Option<(Option<ReadGuard<'_, Values<V, S>>>, M)>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let inner = self.handle.enter()?;
if !inner.ready {
return None;
}
let meta = inner.meta.clone();
let res = ReadGuard::try_map(inner, |inner| inner.data.get(key).map(AsRef::as_ref));
Some((res, meta))
}
pub fn was_dropped(&self) -> bool {
self.handle.was_dropped()
}
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.enter().map_or(false, |x| x.contains_key(key))
}
pub fn contains_value<Q: ?Sized, W: ?Sized>(&self, key: &Q, value: &W) -> bool
where
K: Borrow<Q>,
Aliased<V, crate::aliasing::NoDrop>: Borrow<W>,
Q: Hash + Eq,
W: Hash + Eq,
V: Hash + Eq,
{
self.get_raw(key.borrow())
.map(|x| x.contains(value))
.unwrap_or(false)
}
pub fn map_into<Map, Collector, Target>(&self, mut f: Map) -> Collector
where
Map: FnMut(&K, &Values<V, S>) -> Target,
Collector: FromIterator<Target>,
{
self.enter()
.iter()
.flatten()
.map(|(k, v)| f(k, v))
.collect()
}
}
#[cfg(test)]
mod test {
use crate::new;
#[test]
fn reserve_and_fit() {
const MIN: usize = (1 << 4) + 1;
const MAX: usize = 1 << 6;
let (mut w, r) = new();
w.reserve(0, MAX).publish();
assert!(r.get_raw(&0).unwrap().capacity() >= MAX);
for i in 0..MIN {
w.insert(0, i);
}
w.fit_all().publish();
assert!(r.get_raw(&0).unwrap().capacity() < MAX);
}
}