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