weak_self/
lib.rs

1use std::cell::UnsafeCell;
2use std::fmt;
3use std::sync::{Arc, Weak};
4
5///WeakSelf is simple way to have a Weak pointer inside a data structure pointing to itself.
6///
7///
8///## Use Case
9///
10///
11///Sometimes you want to create a ```struct``` with a pointer to itself or just some other recursive data structure.
12///
13///
14///```rust ignore
15/// struct Foo {
16///     me: &Foo
17/// }
18///
19/// impl Foo {
20///     pub fn new() -> Foo {
21///         let foo = Foo{
22///             me: ????
23///         };
24///         foo
25///     }
26/// }
27///
28///```
29///
30///This create helps you do that:
31///
32///```rust
33/// use weak_self::WeakSelf;
34/// use std::sync::{Arc, Weak};
35/// pub struct Foo {
36///     weak_self: WeakSelf<Foo>
37/// }
38///
39/// impl Foo {
40///     pub fn new() -> Arc<Foo> {
41///         let foo = Arc::new(Foo{
42///             weak_self: WeakSelf::new()
43///         });
44///         foo.weak_self.init(&foo);
45///         foo
46///     }
47///
48///     fn weak(&self) -> Weak<Self> {
49///         self.weak_self.get()
50///     }
51/// }
52///
53///```
54///
55///
56///
57///## Dependencies
58///
59///This package depends on std only
60///
61///## Usage
62///
63///To use WeakSelf, add this to your `Cargo.toml`:
64///
65///```toml
66///[dependencies]
67///weakself = "1.0.2"
68///```
69///
70///
71///## License
72///
73///Licensed under the terms of MIT license and the Apache License (Version 2.0).
74///
75///See [LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE) for details.
76///
77pub struct WeakSelf<T: ?Sized> {
78    cell: UnsafeCell<Option<Weak<T>>>
79}
80
81impl<T: ?Sized> WeakSelf<T> {
82    /// Constructs a new empty WeakSelf<T>
83    pub fn new() -> WeakSelf<T> {
84        WeakSelf {
85            cell: UnsafeCell::new(None)
86        }
87    }
88
89
90    /// Initialize the WeakSelf<T> with an Arc.
91    ///
92    /// Note: content must point be the only existing Arc, otherwise this method will panic
93    pub fn init(&self, content: &Arc<T>) {
94        if Arc::strong_count(content) != 1 || Arc::weak_count(content) != 0 {
95            panic!("Exclusive access to Arc<T> is required while initializing WeakSelf<T>");
96        }
97        let weak = Arc::downgrade(content);
98        unsafe {
99            *self.cell.get() = Some(weak);
100        }
101    }
102
103    /// get Some Weak<T> pointer to the content, or None if not yet initialized
104    pub fn try_get(&self) -> Option<&Weak<T>> {
105        unsafe {
106            match *self.cell.get() {
107                Some(ref weak) => Some(&weak),
108                None => None
109            }
110        }
111    }
112
113    /// get a Weak<T> pointer to the content, or panic if not yet initialized
114    pub fn get(&self) -> Weak<T> {
115        self.try_get().expect("expected WeakSelf to be initialized").clone()
116    }
117}
118
119unsafe impl<T: ?Sized + Sync + Send> Sync for WeakSelf<T> {}
120
121unsafe impl<T: ?Sized + Sync + Send> Send for WeakSelf<T> {}
122
123
124impl<T: ?Sized + fmt::Debug> fmt::Debug for WeakSelf<T> {
125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126        match self.try_get() {
127            None => { write!(f, "Empty WeakSelf<T>") }
128            Some(weak) => fmt::Debug::fmt(weak, f),
129        }
130    }
131}
132
133
134impl<T: ?Sized> Default for WeakSelf<T> {
135    fn default() -> Self {
136        WeakSelf::new()
137    }
138}
139