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