use crate::compat::*;
use crate::{
traits::{WeakElement, WeakKey},
util::hash_one,
};
pub(crate) trait Element: Sized {
type Owned;
type Ref<'a>
where
Self: 'a;
type Handle;
type CachedHash: MaybeHash;
fn as_ref(&self) -> Option<Self::Ref<'_>>;
fn is_expired(&self) -> bool;
fn handle(&self) -> Option<Self::Handle>;
fn from_owned(owned: Self::Owned, cached_hash: Self::CachedHash) -> (Self, Self::Handle);
fn into_owned(self) -> Option<Self::Owned>;
fn owned_ref_from_handle<'a>(&'a self, handle: &'a Self::Handle) -> &'a Self::Owned;
fn owned_from_handle(self, handle: Self::Handle) -> Self::Owned;
fn handle_from_owned(owned: &Self::Owned) -> Self::Handle;
fn reset_from_handle(&mut self, handle: &Self::Handle);
}
pub(crate) trait Key: Element + Sized {
type Key: ?Sized;
fn hash<S: BuildHasher>(&self, hash_builder: &S) -> u64;
fn hash_owned<S: BuildHasher>(strong: &Self::Owned, hash_builder: &S) -> u64;
fn eq_owned(&self, strong: &Self::Owned) -> bool;
fn eq_borrow<Q>(&self, key: &Q) -> bool
where
Q: ?Sized + Hash + Eq,
Self::Key: Borrow<Q>;
}
#[derive(Clone, Debug)]
pub(crate) struct Owned<T> {
pub(crate) val: T,
}
impl<T> Element for Owned<T> {
type Owned = T;
type Ref<'a>
= &'a T
where
T: 'a;
type Handle = ();
type CachedHash = ();
fn is_expired(&self) -> bool {
false
}
fn as_ref(&self) -> Option<Self::Ref<'_>> {
Some(&self.val)
}
fn handle(&self) -> Option<Self::Handle> {
Some(())
}
fn from_owned(val: Self::Owned, _hash: ()) -> (Self, Self::Handle) {
(Owned { val }, ())
}
fn into_owned(self) -> Option<Self::Owned> {
Some(self.val)
}
fn owned_ref_from_handle<'a>(&'a self, _handle: &'a Self::Handle) -> &'a Self::Owned {
&self.val
}
fn owned_from_handle(self, _handle: Self::Handle) -> Self::Owned {
self.val
}
fn handle_from_owned(_owned: &Self::Owned) -> Self::Handle {}
fn reset_from_handle(&mut self, _handle: &Self::Handle) {}
}
impl<T: Hash + Eq> Key for Owned<T> {
type Key = T;
fn hash<S: BuildHasher>(&self, hash_builder: &S) -> u64 {
hash_one(hash_builder, &self.val)
}
fn hash_owned<S: BuildHasher>(strong: &Self::Owned, hash_builder: &S) -> u64 {
hash_one(hash_builder, strong)
}
fn eq_owned(&self, strong: &Self::Owned) -> bool {
self.val.eq(strong)
}
fn eq_borrow<Q>(&self, key: &Q) -> bool
where
Q: ?Sized + Hash + Eq,
Self::Key: Borrow<Q>,
{
self.val.borrow() == key
}
}
pub(crate) trait MaybeHash {
fn new(hash: u64) -> Self;
}
impl MaybeHash for () {
#[allow(clippy::unused_unit, clippy::semicolon_if_nothing_returned)]
fn new(_hash: u64) -> Self {
()
}
}
impl MaybeHash for u64 {
fn new(hash: u64) -> Self {
hash
}
}
#[derive(Clone, Debug)]
pub(crate) struct Weak<T, H> {
pub(crate) val: T,
pub(crate) hash: H,
}
impl<T, H> Element for Weak<T, H>
where
T: WeakElement,
H: MaybeHash,
{
type Owned = T::Strong;
type Ref<'a>
= T::Strong
where
Self: 'a;
type Handle = T::Strong;
type CachedHash = H;
fn is_expired(&self) -> bool {
self.val.is_expired()
}
fn as_ref(&self) -> Option<Self::Ref<'_>> {
self.val.view()
}
fn handle(&self) -> Option<Self::Handle> {
self.val.view()
}
fn from_owned(owned: Self::Owned, hash: H) -> (Self, Self::Handle) {
(
Weak {
val: T::new(&owned),
hash,
},
owned,
)
}
fn into_owned(self) -> Option<Self::Owned> {
self.val.view()
}
fn owned_ref_from_handle<'a>(&'a self, handle: &'a Self::Handle) -> &'a Self::Owned {
handle
}
fn owned_from_handle(self, handle: Self::Handle) -> Self::Owned {
handle
}
fn handle_from_owned(owned: &Self::Owned) -> Self::Handle {
T::clone(owned)
}
fn reset_from_handle(&mut self, handle: &Self::Handle) {
self.val = T::new(handle);
}
}
impl<T> Key for Weak<T, u64>
where
T: WeakKey,
{
type Key = T::Key;
fn hash<S: BuildHasher>(&self, _hash_builder: &S) -> u64 {
self.hash
}
fn hash_owned<S: BuildHasher>(strong: &Self::Owned, hash_builder: &S) -> u64 {
let mut h = hash_builder.build_hasher();
T::hash(strong, &mut h);
h.finish()
}
fn eq_owned(&self, strong: &Self::Owned) -> bool {
if let Some(self_view) = self.val.view() {
T::with_key(strong, |other_as_key| T::equals(&self_view, other_as_key))
} else {
false
}
}
fn eq_borrow<Q>(&self, key: &Q) -> bool
where
Q: ?Sized + Hash + Eq,
Self::Key: Borrow<Q>,
{
if let Some(self_view) = self.val.view() {
T::equals(&self_view, key)
} else {
false
}
}
}