weak_table/traits.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
//! Traits for describing strong and weak pointers and their use as elements and keys.
//!
//! These traits provide mechanisms for converting between weak and strong pointers
//! ([`WeakElement`](trait.WeakElement.html)) and for dereferencing strong pointers
//! ([`WeakKey`](trait.WeakKey.html)). Implementations of these traits are provided for
//! `std::rc::Weak` and `std::sync::Weak`. If you would like to use your own pointer type
//! as a weak element, you need to implement `WeakElement` for your weak pointer type; to use it
//! as a weak key, implement `WeakKey` as well.
use crate::compat::*;
/// Interface for elements that can be stored in weak hash tables.
///
/// This trait applies to the weak version of a reference-counted pointer; it can be used to
/// convert a weak pointer into a strong pointer and back. For example, the impl for
/// `std::rc::Weak<T>` defines the `Strong` associated type as `std::rc::Rc<T>`. Then method
/// `new` can be used to downgrade an `Rc<T>` to a `Weak<T>`, and method `view` can be used to
/// upgrade a `Weak<T>` into an `Rc<T>`, if it's still alive. If we think of the weak pointer as
/// what is stored, then the strong pointer is a temporary view of it.
pub trait WeakElement {
/// The type at which a weak element can be viewed.
///
/// For example, for `std::rc::Weak<T>`, this will be `std::rc::Rc<T>`.
type Strong;
/// Constructs a weak pointer from a strong pointer.
///
/// This is usually implemented by a `downgrade` method.
fn new(view: &Self::Strong) -> Self;
/// Acquires a strong pointer from a weak pointer.
///
/// This is usually implemented by an `upgrade` method.
fn view(&self) -> Option<Self::Strong>;
/// Is the given weak element expired?
///
/// The default implemention checks whether a strong pointer can be obtained via `view`.
fn is_expired(&self) -> bool {
self.view().is_none()
}
/// Clones a strong pointer.
///
/// The default implementation uses `new` and `view`; you should override it.
fn clone(view: &Self::Strong) -> Self::Strong
where Self: Sized
{
Self::new(view).view().expect("WeakElement::clone")
}
}
/// Interface for elements that can act as keys in weak hash tables.
///
/// To use an element as a weak hash map key or weak hash set element), the hash table
/// needs to be able to view the actual key values to hash and compare them. This trait
/// provides the necessary mechanism.
pub trait WeakKey : WeakElement {
/// The underlying key type.
///
/// For example, for `std::rc::Weak<T>`, this will be `T`.
type Key: ?Sized + Eq + Hash;
/// Allows borrowing a view of the key, via a callback.
///
/// Rather than returning a borrowed reference to the actual key, this method passes a
/// reference to the key to a callback with an implicit higher-order lifetime bound. This is
/// necessary to get the lifetimes right in cases where the key is not actually store in the
/// strong pointer.
fn with_key<F, R>(view: &Self::Strong, f: F) -> R
where F: FnOnce(&Self::Key) -> R;
/// Hashes the key `view` into the given `Hasher`.
fn hash<H: Hasher>(view: &Self::Strong, h: &mut H) {
Self::with_key(view, |k| k.hash(h));
}
/// Returns whether the key `view` equals the given `key`.
fn equals<Q>(view: &Self::Strong, key: &Q) -> bool
where Q: ?Sized + Eq,
Self::Key: Borrow<Q>
{
Self::with_key(view, |k| k.borrow() == key)
}
}
impl<T: ?Sized> WeakElement for rc::Weak<T> {
type Strong = rc::Rc<T>;
fn new(view: &Self::Strong) -> Self {
rc::Rc::<T>::downgrade(view)
}
fn view(&self) -> Option<Self::Strong> {
self.upgrade()
}
fn clone(view: &Self::Strong) -> Self::Strong {
view.clone()
}
}
impl<T: ?Sized + Eq + Hash> WeakKey for rc::Weak<T> {
type Key = T;
fn with_key<F, R>(view: &Self::Strong, f: F) -> R
where F: FnOnce(&Self::Key) -> R
{
f(view)
}
}
impl<T: ?Sized> WeakElement for sync::Weak<T> {
type Strong = sync::Arc<T>;
fn new(view: &Self::Strong) -> Self {
sync::Arc::<T>::downgrade(view)
}
fn view(&self) -> Option<Self::Strong> {
self.upgrade()
}
fn clone(view: &Self::Strong) -> Self::Strong {
view.clone()
}
}
impl<T: ?Sized + Eq + Hash> WeakKey for sync::Weak<T>
{
type Key = T;
fn with_key<F, R>(view: &Self::Strong, f: F) -> R
where F: FnOnce(&Self::Key) -> R
{
f(view)
}
}