1use 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::prelude::*;
13use crate::Object;
14use crate::SendWeakRef;
15use crate::WeakRef;
16
17pub trait Property {
23 type Value: HasParamSpec;
24}
25impl<T: HasParamSpec> Property for T {
26 type Value = T;
27}
28impl<T: Property> Property for PhantomData<T> {
29 type Value = T::Value;
30}
31impl<T: Property> Property for RefCell<T> {
32 type Value = T::Value;
33}
34impl<T: Property> Property for Cell<T> {
35 type Value = T::Value;
36}
37impl<T: Property> Property for Mutex<T> {
38 type Value = T::Value;
39}
40impl<T: Property> Property for RwLock<T> {
41 type Value = T::Value;
42}
43impl<T: Property> Property for std::cell::OnceCell<T> {
44 type Value = T::Value;
45}
46impl<T: Property> Property for std::sync::OnceLock<T> {
47 type Value = T::Value;
48}
49impl<T: Property> Property for Rc<T> {
51 type Value = T::Value;
52}
53impl<T: Property> Property for Arc<T> {
54 type Value = T::Value;
55}
56impl<T: IsA<Object> + HasParamSpec> Property for WeakRef<T> {
57 type Value = Option<T>;
58}
59impl<T: IsA<Object> + HasParamSpec> Property for SendWeakRef<T> {
60 type Value = Option<T>;
61}
62
63pub trait PropertyGet {
66 type Value;
67 fn get<R, F: Fn(&Self::Value) -> R>(&self, f: F) -> R;
68}
69
70pub trait PropertySetNested {
75 type SetNestedValue;
76 fn set_nested<F: FnOnce(&mut Self::SetNestedValue)>(&self, f: F);
77}
78
79pub trait PropertySet {
82 type SetValue;
83 fn set(&self, v: Self::SetValue);
84}
85impl<T: PropertySetNested> PropertySet for T {
86 type SetValue = T::SetNestedValue;
87 fn set(&self, v: Self::SetValue) {
88 self.set_nested(|x| *x = v);
89 }
90}
91
92impl<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
99impl<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}
105impl<T> PropertySet for Cell<T> {
106 type SetValue = T;
107 fn set(&self, v: Self::SetValue) {
108 self.set(v);
109 }
110}
111impl<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}
117impl<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
124impl<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}
130impl<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
137impl<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}
143impl<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
150impl<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}
156impl<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}
162impl<T> PropertySet for std::cell::OnceCell<T> {
163 type SetValue = T;
164 fn set(&self, v: Self::SetValue) {
165 if let Err(_v) = self.set(v) {
167 panic!("can't set value of OnceCell multiple times")
168 };
169 }
170}
171impl<T> PropertySet for std::sync::OnceLock<T> {
172 type SetValue = T;
173 fn set(&self, v: Self::SetValue) {
174 if let Err(_v) = self.set(v) {
176 panic!("can't set value of OnceCell multiple times")
177 };
178 }
179}
180
181impl<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}
188impl<T: IsA<Object>> PropertySet for WeakRef<T> {
189 type SetValue = Option<T>;
190
191 fn set(&self, v: Self::SetValue) {
192 self.set(v.as_ref())
193 }
194}
195impl<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}
202impl<T: IsA<Object>> PropertySet for SendWeakRef<T> {
203 type SetValue = Option<T>;
204
205 fn set(&self, v: Self::SetValue) {
206 WeakRef::set(self, v.as_ref());
207 }
208}
209
210impl<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}
217impl<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
224impl<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}
230impl<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
237macro_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
257impl_atomic!(std::sync::atomic::AtomicBool, bool);
258impl_atomic!(std::sync::atomic::AtomicI8, i8);
259impl_atomic!(std::sync::atomic::AtomicI32, i32);
260#[cfg(target_has_atomic = "64")]
261impl_atomic!(std::sync::atomic::AtomicI64, i64);
262impl_atomic!(std::sync::atomic::AtomicU8, u8);
263impl_atomic!(std::sync::atomic::AtomicU32, u32);
264#[cfg(target_has_atomic = "64")]
265impl_atomic!(std::sync::atomic::AtomicU64, u64);