1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::cell::Cell; |
4 | use std::cell::RefCell; |
5 | use std::marker::PhantomData; |
6 | use std::rc::Rc; |
7 | use std::sync::atomic::Ordering; |
8 | use std::sync::Arc; |
9 | use std::sync::Mutex; |
10 | use std::sync::RwLock; |
11 | |
12 | use crate::prelude::*; |
13 | use crate::Object; |
14 | use crate::SendWeakRef; |
15 | use crate::WeakRef; |
16 | |
17 | // rustdoc-stripper-ignore-next |
18 | /// A type that can be used as a property. It covers every type which have an associated `ParamSpec` |
19 | /// (`HasParamSpec`) and some useful types wrapping `HasParamSpec`. |
20 | /// The definition is recursive, so you can nest many `Property`s together. The final `ParamSpec` will |
21 | /// be the one of the innermost type |
22 | pub trait Property { |
23 | type Value: HasParamSpec; |
24 | } |
25 | impl<T: HasParamSpec> Property for T { |
26 | type Value = T; |
27 | } |
28 | impl<T: Property> Property for PhantomData<T> { |
29 | type Value = T::Value; |
30 | } |
31 | impl<T: Property> Property for RefCell<T> { |
32 | type Value = T::Value; |
33 | } |
34 | impl<T: Property> Property for Cell<T> { |
35 | type Value = T::Value; |
36 | } |
37 | impl<T: Property> Property for Mutex<T> { |
38 | type Value = T::Value; |
39 | } |
40 | impl<T: Property> Property for RwLock<T> { |
41 | type Value = T::Value; |
42 | } |
43 | impl<T: Property> Property for std::cell::OnceCell<T> { |
44 | type Value = T::Value; |
45 | } |
46 | impl<T: Property> Property for std::sync::OnceLock<T> { |
47 | type Value = T::Value; |
48 | } |
49 | // Handle smart pointers transparently |
50 | impl<T: Property> Property for Rc<T> { |
51 | type Value = T::Value; |
52 | } |
53 | impl<T: Property> Property for Arc<T> { |
54 | type Value = T::Value; |
55 | } |
56 | impl<T: IsA<Object> + HasParamSpec> Property for WeakRef<T> { |
57 | type Value = Option<T>; |
58 | } |
59 | impl<T: IsA<Object> + HasParamSpec> Property for SendWeakRef<T> { |
60 | type Value = Option<T>; |
61 | } |
62 | |
63 | // rustdoc-stripper-ignore-next |
64 | /// A container type implementing this trait can be read by the default getter generated by the [`Properties`](crate::Properties) macro. |
65 | pub trait PropertyGet { |
66 | type Value; |
67 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R; |
68 | } |
69 | |
70 | // rustdoc-stripper-ignore-next |
71 | /// A container type implementing this trait can be written by the default setter generated by the [`Properties`](crate::Properties) macro. |
72 | /// It takes a `FnOnce(&mut Self::Value)` so that the caller may access nested fields of a struct |
73 | /// by doing `${Self::Value}.member` |
74 | pub trait PropertySetNested { |
75 | type SetNestedValue; |
76 | fn set_nested<F: FnOnce(&mut Self::SetNestedValue)>(&self, f: F); |
77 | } |
78 | |
79 | // rustdoc-stripper-ignore-next |
80 | /// A container type implementing this trait can be written by the default setter generated by the [`Properties`](crate::Properties) macro. |
81 | pub trait PropertySet { |
82 | type SetValue; |
83 | fn set(&self, v: Self::SetValue); |
84 | } |
85 | impl<T: PropertySetNested> PropertySet for T { |
86 | type SetValue = T::SetNestedValue; |
87 | fn set(&self, v: Self::SetValue) { |
88 | self.set_nested(|x: &mut ::SetNestedValue| *x = v); |
89 | } |
90 | } |
91 | |
92 | impl<T: HasParamSpec> PropertyGet for T { |
93 | type Value = T; |
94 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
95 | f(self) |
96 | } |
97 | } |
98 | |
99 | impl<T: Copy> PropertyGet for Cell<T> { |
100 | type Value = T; |
101 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
102 | f(&Cell::get(self)) |
103 | } |
104 | } |
105 | impl<T> PropertySet for Cell<T> { |
106 | type SetValue = T; |
107 | fn set(&self, v: Self::SetValue) { |
108 | self.set(val:v); |
109 | } |
110 | } |
111 | impl<T> PropertyGet for RefCell<T> { |
112 | type Value = T; |
113 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
114 | f(&self.borrow()) |
115 | } |
116 | } |
117 | impl<T> PropertySetNested for RefCell<T> { |
118 | type SetNestedValue = T; |
119 | fn set_nested<F: FnOnce(&mut Self::SetNestedValue)>(&self, f: F) { |
120 | f(&mut self.borrow_mut()); |
121 | } |
122 | } |
123 | |
124 | impl<T> PropertyGet for Mutex<T> { |
125 | type Value = T; |
126 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
127 | f(&self.lock().unwrap()) |
128 | } |
129 | } |
130 | impl<T> PropertySetNested for Mutex<T> { |
131 | type SetNestedValue = T; |
132 | fn set_nested<F: FnOnce(&mut Self::SetNestedValue)>(&self, f: F) { |
133 | f(&mut self.lock().unwrap()); |
134 | } |
135 | } |
136 | |
137 | impl<T> PropertyGet for RwLock<T> { |
138 | type Value = T; |
139 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
140 | f(&self.read().unwrap()) |
141 | } |
142 | } |
143 | impl<T> PropertySetNested for RwLock<T> { |
144 | type SetNestedValue = T; |
145 | fn set_nested<F: FnOnce(&mut Self::SetNestedValue)>(&self, f: F) { |
146 | f(&mut self.write().unwrap()); |
147 | } |
148 | } |
149 | |
150 | impl<T> PropertyGet for std::cell::OnceCell<T> { |
151 | type Value = T; |
152 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
153 | f(self.get().unwrap()) |
154 | } |
155 | } |
156 | impl<T> PropertyGet for std::sync::OnceLock<T> { |
157 | type Value = T; |
158 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
159 | f(self.get().unwrap()) |
160 | } |
161 | } |
162 | impl<T> PropertySet for std::cell::OnceCell<T> { |
163 | type SetValue = T; |
164 | fn set(&self, v: Self::SetValue) { |
165 | // I can't use `unwrap` because I would have to add a `Debug` bound to _v |
166 | if let Err(_v: T) = self.set(v) { |
167 | panic!("can't set value of OnceCell multiple times" ) |
168 | }; |
169 | } |
170 | } |
171 | impl<T> PropertySet for std::sync::OnceLock<T> { |
172 | type SetValue = T; |
173 | fn set(&self, v: Self::SetValue) { |
174 | // I can't use `unwrap` because I would have to add a `Debug` bound to _v |
175 | if let Err(_v: T) = self.set(v) { |
176 | panic!("can't set value of OnceCell multiple times" ) |
177 | }; |
178 | } |
179 | } |
180 | |
181 | impl<T: IsA<Object>> PropertyGet for WeakRef<T> { |
182 | type Value = Option<T>; |
183 | |
184 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
185 | f(&self.upgrade()) |
186 | } |
187 | } |
188 | impl<T: IsA<Object>> PropertySet for WeakRef<T> { |
189 | type SetValue = Option<T>; |
190 | |
191 | fn set(&self, v: Self::SetValue) { |
192 | self.set(obj:v.as_ref()) |
193 | } |
194 | } |
195 | impl<T: IsA<Object>> PropertyGet for SendWeakRef<T> { |
196 | type Value = Option<T>; |
197 | |
198 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
199 | f(&self.upgrade()) |
200 | } |
201 | } |
202 | impl<T: IsA<Object>> PropertySet for SendWeakRef<T> { |
203 | type SetValue = Option<T>; |
204 | |
205 | fn set(&self, v: Self::SetValue) { |
206 | WeakRef::set(self, obj:v.as_ref()); |
207 | } |
208 | } |
209 | |
210 | // Smart pointers wrapping a `PropertyRead`/`PropertyWrite` |
211 | impl<T: PropertyGet> PropertyGet for Rc<T> { |
212 | type Value = T::Value; |
213 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
214 | (**self).get(f) |
215 | } |
216 | } |
217 | impl<T: PropertySetNested> PropertySetNested for Rc<T> { |
218 | type SetNestedValue = T::SetNestedValue; |
219 | fn set_nested<F: FnOnce(&mut Self::SetNestedValue)>(&self, f: F) { |
220 | (**self).set_nested(f) |
221 | } |
222 | } |
223 | |
224 | impl<T: PropertyGet> PropertyGet for Arc<T> { |
225 | type Value = T::Value; |
226 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
227 | (**self).get(f) |
228 | } |
229 | } |
230 | impl<T: PropertySetNested> PropertySetNested for Arc<T> { |
231 | type SetNestedValue = T::SetNestedValue; |
232 | fn set_nested<F: FnOnce(&mut Self::SetNestedValue)>(&self, f: F) { |
233 | (**self).set_nested(f) |
234 | } |
235 | } |
236 | |
237 | macro_rules! impl_atomic { |
238 | ($atomic:ty, $valuety:ty) => { |
239 | impl Property for $atomic { |
240 | type Value = $valuety; |
241 | } |
242 | impl PropertyGet for $atomic { |
243 | type Value = $valuety; |
244 | fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R { |
245 | f(&self.load(Ordering::Acquire)) |
246 | } |
247 | } |
248 | impl PropertySet for $atomic { |
249 | type SetValue = $valuety; |
250 | fn set(&self, v: Self::SetValue) { |
251 | self.store(v, Ordering::Release); |
252 | } |
253 | } |
254 | }; |
255 | } |
256 | |
257 | impl_atomic!(std::sync::atomic::AtomicBool, bool); |
258 | impl_atomic!(std::sync::atomic::AtomicI8, i8); |
259 | impl_atomic!(std::sync::atomic::AtomicI32, i32); |
260 | #[cfg (target_has_atomic = "64" )] |
261 | impl_atomic!(std::sync::atomic::AtomicI64, i64); |
262 | impl_atomic!(std::sync::atomic::AtomicU8, u8); |
263 | impl_atomic!(std::sync::atomic::AtomicU32, u32); |
264 | #[cfg (target_has_atomic = "64" )] |
265 | impl_atomic!(std::sync::atomic::AtomicU64, u64); |
266 | |