1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 //! `IMPL` Shared (reference counted) wrapper implementation.
4 
5 use crate::translate::*;
6 use std::cmp;
7 use std::fmt;
8 use std::hash::{Hash, Hasher};
9 use std::marker::PhantomData;
10 use std::ptr;
11 
12 /// Wrapper implementations for shared types. See `wrapper!`.
13 #[macro_export]
14 macro_rules! glib_shared_wrapper {
15     ([$($attr:meta)*] $name:ident, $ffi_name:ty, @ref $ref_arg:ident $ref_expr:expr,
16      @unref $unref_arg:ident $unref_expr:expr,
17      @type_ $get_type_expr:expr) => {
18         $crate::glib_shared_wrapper!([$($attr)*] $name, $ffi_name, @ref $ref_arg $ref_expr,
19             @unref $unref_arg $unref_expr);
20 
21         impl $crate::types::StaticType for $name {
22             fn static_type() -> $crate::types::Type {
23                 #[allow(unused_unsafe)]
24                 unsafe { $crate::translate::from_glib($get_type_expr) }
25             }
26         }
27 
28         #[doc(hidden)]
29         impl $crate::value::ValueType for $name {
30             type Type = $name;
31         }
32 
33         #[doc(hidden)]
34         unsafe impl<'a> $crate::value::FromValue<'a> for $name {
35             type Checker = $crate::value::GenericValueTypeOrNoneChecker<Self>;
36 
37             unsafe fn from_value(value: &'a $crate::Value) -> Self {
38                 let ptr = $crate::gobject_ffi::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0);
39                 assert!(!ptr.is_null());
40                 <$name as $crate::translate::FromGlibPtrFull<*mut $ffi_name>>::from_glib_full(ptr as *mut $ffi_name)
41             }
42         }
43 
44         #[doc(hidden)]
45         impl $crate::value::ToValue for $name {
46             fn to_value(&self) -> $crate::Value {
47                 unsafe {
48                     let mut value = $crate::Value::from_type(<$name as $crate::StaticType>::static_type());
49                     $crate::gobject_ffi::g_value_take_boxed(
50                         $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
51                         $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(self) as *mut _,
52                     );
53                     value
54                 }
55             }
56 
57             fn value_type(&self) -> $crate::Type {
58                 <$name as $crate::StaticType>::static_type()
59             }
60         }
61 
62         #[doc(hidden)]
63         impl $crate::value::ToValueOptional for $name {
64             fn to_value_optional(s: Option<&Self>) -> $crate::Value {
65                 let mut value = $crate::Value::for_value_type::<Self>();
66                 unsafe {
67                     $crate::gobject_ffi::g_value_take_boxed(
68                         $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
69                         $crate::translate::ToGlibPtr::<*mut $ffi_name>::to_glib_full(&s) as *mut _,
70                     );
71                 }
72 
73                 value
74             }
75         }
76     };
77 
78     ([$($attr:meta)*] $name:ident, $ffi_name:ty, @ref $ref_arg:ident $ref_expr:expr,
79      @unref $unref_arg:ident $unref_expr:expr) => {
80         $(#[$attr])*
81         #[derive(Clone)]
82         pub struct $name($crate::shared::Shared<$ffi_name, $name>);
83 
84         #[doc(hidden)]
85         impl $crate::shared::SharedMemoryManager<$ffi_name> for $name {
86             #[inline]
87             unsafe fn ref_($ref_arg: *mut $ffi_name) {
88                 $ref_expr;
89             }
90 
91             #[inline]
92             #[allow(clippy::no_effect)]
93             unsafe fn unref($unref_arg: *mut $ffi_name) {
94                 $unref_expr;
95             }
96         }
97 
98         #[doc(hidden)]
99         impl $crate::translate::GlibPtrDefault for $name {
100             type GlibType = *mut $ffi_name;
101         }
102 
103         #[doc(hidden)]
104         impl<'a> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name {
105             type Storage = &'a $crate::shared::Shared<$ffi_name, $name>;
106 
107             #[inline]
108             fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> {
109                 let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.0);
110                 $crate::translate::Stash(stash.0, stash.1)
111             }
112 
113             #[inline]
114             fn to_glib_full(&self) -> *mut $ffi_name {
115                 $crate::translate::ToGlibPtr::to_glib_full(&self.0)
116             }
117         }
118 
119         #[doc(hidden)]
120         impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *mut *mut $ffi_name> for $name {
121             type Storage = (Vec<$crate::translate::Stash<'a, *mut $ffi_name, $name>>, Option<Vec<*mut $ffi_name>>);
122 
123             fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut *mut $ffi_name, Self::Storage) {
124                 let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
125                 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
126                 v_ptr.push(std::ptr::null_mut() as *mut $ffi_name);
127 
128                 (v_ptr.as_ptr() as *mut *mut $ffi_name, (v, Some(v_ptr)))
129             }
130 
131             fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut *mut $ffi_name, Self::Storage) {
132                 let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
133 
134                 let v_ptr = unsafe {
135                     let v_ptr = $crate::ffi::g_malloc0(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
136 
137                     for (i, s) in v.iter().enumerate() {
138                         std::ptr::write(v_ptr.add(i), s.0);
139                     }
140 
141                     v_ptr
142                 };
143 
144                 (v_ptr, (v, None))
145             }
146 
147             fn to_glib_full_from_slice(t: &[$name]) -> *mut *mut $ffi_name {
148                 unsafe {
149                     let v_ptr = $crate::ffi::g_malloc0(std::mem::size_of::<*mut $ffi_name>() * (t.len() + 1)) as *mut *mut $ffi_name;
150 
151                     for (i, s) in t.iter().enumerate() {
152                         std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s));
153                     }
154 
155                     v_ptr
156                 }
157             }
158         }
159 
160         #[doc(hidden)]
161         impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *const *mut $ffi_name> for $name {
162             type Storage = (Vec<$crate::translate::Stash<'a, *mut $ffi_name, $name>>, Option<Vec<*mut $ffi_name>>);
163 
164             fn to_glib_none_from_slice(t: &'a [$name]) -> (*const *mut $ffi_name, Self::Storage) {
165                 let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *mut $ffi_name>::to_glib_none_from_slice(t);
166                 (ptr as *const *mut $ffi_name, stash)
167             }
168 
169             fn to_glib_container_from_slice(_: &'a [$name]) -> (*const *mut $ffi_name, Self::Storage) {
170                 // Can't have consumer free a *const pointer
171                 unimplemented!()
172             }
173 
174             fn to_glib_full_from_slice(_: &[$name]) -> *const *mut $ffi_name {
175                 // Can't have consumer free a *const pointer
176                 unimplemented!()
177             }
178         }
179 
180         #[doc(hidden)]
181         impl $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name {
182             #[inline]
183             unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
184                 $name($crate::translate::from_glib_none(ptr))
185             }
186         }
187 
188         #[doc(hidden)]
189         impl $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name {
190             #[inline]
191             unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self {
192                 $name($crate::translate::from_glib_none(ptr))
193             }
194         }
195 
196         #[doc(hidden)]
197         impl $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name {
198             #[inline]
199             unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
200                 $name($crate::translate::from_glib_full(ptr))
201             }
202         }
203 
204         #[doc(hidden)]
205         impl $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name {
206             #[inline]
207             unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> $crate::translate::Borrowed<Self> {
208                 $crate::translate::Borrowed::new(
209                     $name(
210                         $crate::translate::from_glib_borrow::<_, $crate::shared::Shared<_, _>>(ptr).into_inner()
211                     )
212                 )
213             }
214         }
215 
216         #[doc(hidden)]
217         impl $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name {
218             #[inline]
219             unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> $crate::translate::Borrowed<Self> {
220                 $crate::translate::from_glib_borrow::<_, $name>(ptr as *mut $ffi_name)
221             }
222         }
223 
224         #[doc(hidden)]
225         impl $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
226             unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
227                 if num == 0 || ptr.is_null() {
228                     return Vec::new();
229                 }
230 
231                 let mut res = Vec::with_capacity(num);
232                 for i in 0..num {
233                     res.push($crate::translate::from_glib_none(std::ptr::read(ptr.add(i))));
234                 }
235                 res
236             }
237 
238             unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
239                 let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
240                 $crate::ffi::g_free(ptr as *mut _);
241                 res
242             }
243 
244             unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
245                 if num == 0 || ptr.is_null() {
246                     return Vec::new();
247                 }
248 
249                 let mut res = Vec::with_capacity(num);
250                 for i in 0..num {
251                     res.push($crate::translate::from_glib_full(std::ptr::read(ptr.add(i))));
252                 }
253                 $crate::ffi::g_free(ptr as *mut _);
254                 res
255             }
256         }
257 
258         #[doc(hidden)]
259         impl $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
260             unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
261                 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
262             }
263 
264             unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
265                 $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
266             }
267 
268             unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
269                 $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
270             }
271         }
272 
273         #[doc(hidden)]
274         impl $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name {
275             unsafe fn from_glib_none_num_as_vec(ptr: *const *mut $ffi_name, num: usize) -> Vec<Self> {
276                 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
277             }
278 
279             unsafe fn from_glib_container_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
280                 // Can't free a *const
281                 unimplemented!()
282             }
283 
284             unsafe fn from_glib_full_num_as_vec(_: *const *mut $ffi_name, _: usize) -> Vec<Self> {
285                 // Can't free a *const
286                 unimplemented!()
287             }
288         }
289 
290         #[doc(hidden)]
291         impl $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *const *mut $ffi_name> for $name {
292             unsafe fn from_glib_none_as_vec(ptr: *const *mut $ffi_name) -> Vec<Self> {
293                 $crate::translate::FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
294             }
295 
296             unsafe fn from_glib_container_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
297                 // Can't free a *const
298                 unimplemented!()
299             }
300 
301             unsafe fn from_glib_full_as_vec(_: *const *mut $ffi_name) -> Vec<Self> {
302                 // Can't free a *const
303                 unimplemented!()
304             }
305         }
306     }
307 }
308 
309 pub trait SharedMemoryManager<T> {
310     /// # Safety
311     ///
312     /// Callers are responsible for ensuring that a matching call to `unref`
313     /// is made at an appropriate time.
ref_(ptr: *mut T)314     unsafe fn ref_(ptr: *mut T);
315 
316     /// # Safety
317     ///
318     /// Callers are responsible for ensuring that a matching call to `ref` was
319     /// made before this is called, and that the pointer is not used after the
320     /// `unref` call.
unref(ptr: *mut T)321     unsafe fn unref(ptr: *mut T);
322 }
323 
324 /// Encapsulates memory management logic for shared types.
325 pub struct Shared<T, MM: SharedMemoryManager<T>> {
326     inner: ptr::NonNull<T>,
327     mm: PhantomData<*const MM>,
328 }
329 
330 impl<T, MM: SharedMemoryManager<T>> Drop for Shared<T, MM> {
drop(&mut self)331     fn drop(&mut self) {
332         unsafe {
333             MM::unref(self.inner.as_ptr());
334         }
335     }
336 }
337 
338 impl<T, MM: SharedMemoryManager<T>> Clone for Shared<T, MM> {
clone(&self) -> Self339     fn clone(&self) -> Self {
340         unsafe {
341             MM::ref_(self.inner.as_ptr());
342         }
343         Self {
344             inner: self.inner,
345             mm: PhantomData,
346         }
347     }
348 }
349 
350 impl<T, MM: SharedMemoryManager<T>> fmt::Debug for Shared<T, MM> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result351     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
352         f.debug_struct("Shared")
353             .field("inner", &self.inner)
354             .finish()
355     }
356 }
357 
358 impl<T, MM: SharedMemoryManager<T>> PartialOrd for Shared<T, MM> {
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>359     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
360         self.inner.partial_cmp(&other.inner)
361     }
362 }
363 
364 impl<T, MM: SharedMemoryManager<T>> Ord for Shared<T, MM> {
cmp(&self, other: &Self) -> cmp::Ordering365     fn cmp(&self, other: &Self) -> cmp::Ordering {
366         self.inner.cmp(&other.inner)
367     }
368 }
369 
370 impl<T, MM: SharedMemoryManager<T>> PartialEq for Shared<T, MM> {
eq(&self, other: &Self) -> bool371     fn eq(&self, other: &Self) -> bool {
372         self.inner == other.inner
373     }
374 }
375 
376 impl<T, MM: SharedMemoryManager<T>> Eq for Shared<T, MM> {}
377 
378 impl<T, MM: SharedMemoryManager<T>> Hash for Shared<T, MM> {
hash<H>(&self, state: &mut H) where H: Hasher,379     fn hash<H>(&self, state: &mut H)
380     where
381         H: Hasher,
382     {
383         self.inner.hash(state)
384     }
385 }
386 
387 impl<'a, T: 'static, MM> ToGlibPtr<'a, *mut T> for Shared<T, MM>
388 where
389     MM: SharedMemoryManager<T> + 'static,
390 {
391     type Storage = &'a Self;
392 
393     #[inline]
to_glib_none(&'a self) -> Stash<'a, *mut T, Self>394     fn to_glib_none(&'a self) -> Stash<'a, *mut T, Self> {
395         Stash(self.inner.as_ptr(), self)
396     }
397 
398     #[inline]
to_glib_full(&self) -> *mut T399     fn to_glib_full(&self) -> *mut T {
400         unsafe {
401             MM::ref_(self.inner.as_ptr());
402         }
403         self.inner.as_ptr()
404     }
405 }
406 
407 impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrNone<*mut T> for Shared<T, MM> {
408     #[inline]
from_glib_none(ptr: *mut T) -> Self409     unsafe fn from_glib_none(ptr: *mut T) -> Self {
410         assert!(!ptr.is_null());
411         MM::ref_(ptr);
412         Self {
413             inner: ptr::NonNull::new_unchecked(ptr),
414             mm: PhantomData,
415         }
416     }
417 }
418 
419 impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrNone<*const T> for Shared<T, MM> {
420     #[inline]
from_glib_none(ptr: *const T) -> Self421     unsafe fn from_glib_none(ptr: *const T) -> Self {
422         assert!(!ptr.is_null());
423         MM::ref_(ptr as *mut _);
424         Self {
425             inner: ptr::NonNull::new_unchecked(ptr as *mut _),
426             mm: PhantomData,
427         }
428     }
429 }
430 
431 impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrFull<*mut T> for Shared<T, MM> {
432     #[inline]
from_glib_full(ptr: *mut T) -> Self433     unsafe fn from_glib_full(ptr: *mut T) -> Self {
434         assert!(!ptr.is_null());
435         Self {
436             inner: ptr::NonNull::new_unchecked(ptr),
437             mm: PhantomData,
438         }
439     }
440 }
441 
442 impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrBorrow<*mut T> for Shared<T, MM> {
443     #[inline]
from_glib_borrow(ptr: *mut T) -> Borrowed<Self>444     unsafe fn from_glib_borrow(ptr: *mut T) -> Borrowed<Self> {
445         assert!(!ptr.is_null());
446         Borrowed::new(Self {
447             inner: ptr::NonNull::new_unchecked(ptr),
448             mm: PhantomData,
449         })
450     }
451 }
452