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