use std::borrow::Borrow;
use std::fmt::{self, Debug};
use std::hash::{BuildHasher, Hash, RandomState};
use crate::OnceMap;
pub struct RegisteredOnceMap<K, V, S = RandomState>(OnceMap<K, V, S>);
impl<K: Eq + Hash + Debug, V: Debug, S: BuildHasher + Clone> Debug for RegisteredOnceMap<K, V, S> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
impl<K: Eq + Hash + Clone, V: Clone, S: BuildHasher + Clone> RegisteredOnceMap<K, V, S> {
pub fn register(&self, key: K) -> bool {
self.0.register(key)
}
pub fn register_entry(&self, key: K) -> Registration<RegisteredEntry<'_, K, V, S>> {
let registered = self.0.register(key.clone());
let entry = RegisteredEntry { map: &self.0, key };
if registered {
Registration::New(entry)
} else {
Registration::Existing(entry)
}
}
pub fn get_registered(&self, key: K) -> Option<RegisteredEntry<'_, K, V, S>> {
self.0
.items
.pin()
.contains_key(&key)
.then_some(RegisteredEntry { map: &self.0, key })
}
pub async fn register_or_wait(&self, key: &K) -> Option<V> {
self.0.register_or_wait(key).await
}
pub fn done(&self, key: K, value: V) {
self.0.done(key, value);
}
pub fn get<Q: ?Sized + Hash + Eq>(&self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
{
self.0.get(key)
}
pub fn remove<Q: ?Sized + Hash + Eq>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
{
self.0.remove(key)
}
}
impl<K: Eq + Hash + Clone, V, S: Default + BuildHasher + Clone> Default
for RegisteredOnceMap<K, V, S>
{
fn default() -> Self {
Self(OnceMap::default())
}
}
impl<K: Eq + Hash, V, S: Default + BuildHasher + Clone> FromIterator<(K, V)>
for RegisteredOnceMap<K, V, S>
{
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
Self(OnceMap::from_iter(iter))
}
}
#[derive(Debug)]
pub enum Registration<T> {
New(T),
Existing(T),
}
#[derive(Clone)]
pub struct RegisteredEntry<'a, K, V, S = RandomState> {
map: &'a OnceMap<K, V, S>,
key: K,
}
impl<K: Debug, V, S> Debug for RegisteredEntry<'_, K, V, S> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_tuple("RegisteredEntry")
.field(&self.key)
.finish()
}
}
impl<K: Eq + Hash + Clone, V: Clone, S: BuildHasher + Clone> RegisteredEntry<'_, K, V, S> {
pub fn key(&self) -> &K {
&self.key
}
pub async fn wait(&self) -> V {
self.map
.wait_registered(&self.key)
.await
.expect("registered entries cannot be removed while borrowed")
}
pub fn wait_blocking(&self) -> V {
futures::executor::block_on(self.wait())
}
}