1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | // rustdoc-stripper-ignore-next |
4 | //! `IMPL` Boxed wrapper implementation. |
5 | |
6 | use std::{ |
7 | cmp, fmt, |
8 | hash::{Hash, Hasher}, |
9 | marker::PhantomData, |
10 | ops::{Deref, DerefMut}, |
11 | ptr, |
12 | }; |
13 | |
14 | use crate::translate::*; |
15 | |
16 | // rustdoc-stripper-ignore-next |
17 | /// Wrapper implementations for Boxed types. See `wrapper!`. |
18 | #[macro_export ] |
19 | macro_rules! glib_boxed_wrapper { |
20 | ([$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $ffi_name:ty, |
21 | @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr |
22 | $(, @type_ $get_type_expr:expr)?) => { |
23 | $crate::glib_boxed_wrapper!(@generic_impl [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $ffi_name); |
24 | |
25 | $crate::glib_boxed_wrapper!( |
26 | @memory_manager_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $ffi_name, |
27 | @copy $copy_arg $copy_expr, @free $free_arg $free_expr |
28 | ); |
29 | |
30 | $crate::glib_boxed_wrapper!(@value_impl $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $ffi_name $(, @type_ $get_type_expr)?); |
31 | }; |
32 | |
33 | (@generic_impl [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $ffi_name:ty) => { |
34 | $(#[$attr])* |
35 | #[doc = " \n\nGLib type: Boxed type with copy-on-clone semantics." ] |
36 | #[repr(transparent)] |
37 | $visibility struct $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? { |
38 | inner: $crate::boxed::Boxed<$ffi_name, Self>, |
39 | } |
40 | |
41 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $name $(<$($generic),+>)? { |
42 | #[doc = "Return the inner pointer to the underlying C value." ] |
43 | #[inline] |
44 | pub fn as_ptr(&self) -> *mut $ffi_name { |
45 | unsafe { *(self as *const Self as *const *const $ffi_name) as *mut $ffi_name } |
46 | } |
47 | |
48 | #[doc = "Borrows the underlying C value." ] |
49 | #[inline] |
50 | pub unsafe fn from_glib_ptr_borrow(ptr: &*mut $ffi_name) -> &Self { |
51 | debug_assert_eq!( |
52 | std::mem::size_of::<Self>(), |
53 | std::mem::size_of::<$crate::ffi::gpointer>() |
54 | ); |
55 | debug_assert!(!ptr.is_null()); |
56 | &*(ptr as *const *mut $ffi_name as *const Self) |
57 | } |
58 | |
59 | #[doc = "Borrows the underlying C value mutably." ] |
60 | #[inline] |
61 | pub unsafe fn from_glib_ptr_borrow_mut(ptr: &mut *mut $ffi_name) -> &mut Self { |
62 | debug_assert_eq!( |
63 | std::mem::size_of::<Self>(), |
64 | std::mem::size_of::<$crate::ffi::gpointer>() |
65 | ); |
66 | debug_assert!(!ptr.is_null()); |
67 | &mut *(ptr as *mut *mut $ffi_name as *mut Self) |
68 | } |
69 | } |
70 | |
71 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::clone::Clone for $name $(<$($generic),+>)? { |
72 | #[doc = "Copies the boxed type with the type-specific copy function." ] |
73 | #[inline] |
74 | fn clone(&self) -> Self { |
75 | Self { |
76 | inner: std::clone::Clone::clone(&self.inner), |
77 | } |
78 | } |
79 | } |
80 | |
81 | #[doc(hidden)] |
82 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::GlibPtrDefault for $name $(<$($generic),+>)? { |
83 | type GlibType = *mut $ffi_name; |
84 | } |
85 | |
86 | #[doc(hidden)] |
87 | unsafe impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::TransparentPtrType for $name $(<$($generic),+>)? {} |
88 | |
89 | #[doc(hidden)] |
90 | impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name $(<$($generic),+>)? { |
91 | type Storage = std::marker::PhantomData<&'a $crate::boxed::Boxed<$ffi_name, Self>>; |
92 | |
93 | #[inline] |
94 | fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> { |
95 | let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.inner); |
96 | $crate::translate::Stash(stash.0, stash.1) |
97 | } |
98 | |
99 | #[inline] |
100 | fn to_glib_full(&self) -> *const $ffi_name { |
101 | $crate::translate::ToGlibPtr::to_glib_full(&self.inner) |
102 | } |
103 | } |
104 | |
105 | #[doc(hidden)] |
106 | impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtr<'a, *mut $ffi_name> for $name $(<$($generic),+>)? { |
107 | type Storage = std::marker::PhantomData<&'a $crate::boxed::Boxed<$ffi_name, Self>>; |
108 | |
109 | #[inline] |
110 | fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *mut $ffi_name, Self> { |
111 | let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.inner); |
112 | $crate::translate::Stash(stash.0 as *mut _, stash.1) |
113 | } |
114 | |
115 | #[inline] |
116 | fn to_glib_full(&self) -> *mut $ffi_name { |
117 | $crate::translate::ToGlibPtr::to_glib_full(&self.inner) as *mut _ |
118 | } |
119 | } |
120 | |
121 | #[doc(hidden)] |
122 | impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibPtrMut<'a, *mut $ffi_name> for $name $(<$($generic),+>)? { |
123 | type Storage = std::marker::PhantomData<&'a mut $crate::boxed::Boxed<$ffi_name, Self>>; |
124 | |
125 | #[inline] |
126 | fn to_glib_none_mut(&'a mut self) -> $crate::translate::StashMut<'a, *mut $ffi_name, Self> { |
127 | let stash = $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut self.inner); |
128 | $crate::translate::StashMut(stash.0, stash.1) |
129 | } |
130 | } |
131 | |
132 | #[doc(hidden)] |
133 | impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *mut *const $ffi_name> for $name $(<$($generic),+>)? { |
134 | type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*const $ffi_name>>); |
135 | |
136 | fn to_glib_none_from_slice(t: &'a [Self]) -> (*mut *const $ffi_name, Self::Storage) { |
137 | let mut v_ptr = Vec::with_capacity(t.len() + 1); |
138 | unsafe { |
139 | let ptr = v_ptr.as_mut_ptr(); |
140 | std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *const $ffi_name, ptr, t.len()); |
141 | std::ptr::write(ptr.add(t.len()), std::ptr::null_mut()); |
142 | v_ptr.set_len(t.len() + 1); |
143 | } |
144 | |
145 | (v_ptr.as_ptr() as *mut *const $ffi_name, (std::marker::PhantomData, Some(v_ptr))) |
146 | } |
147 | |
148 | fn to_glib_container_from_slice(t: &'a [Self]) -> (*mut *const $ffi_name, Self::Storage) { |
149 | let v_ptr = unsafe { |
150 | let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*const $ffi_name>() * (t.len() + 1)) as *mut *const $ffi_name; |
151 | |
152 | std::ptr::copy_nonoverlapping(t.as_ptr() as *mut *const $ffi_name, v_ptr, t.len()); |
153 | std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut()); |
154 | |
155 | v_ptr |
156 | }; |
157 | |
158 | (v_ptr, (std::marker::PhantomData, None)) |
159 | } |
160 | |
161 | fn to_glib_full_from_slice(t: &[Self]) -> *mut *const $ffi_name { |
162 | unsafe { |
163 | let v_ptr = $crate::ffi::g_malloc(std::mem::size_of::<*const $ffi_name>() * (t.len() + 1)) as *mut *const $ffi_name; |
164 | |
165 | for (i, s) in t.iter().enumerate() { |
166 | std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s)); |
167 | } |
168 | std::ptr::write(v_ptr.add(t.len()), std::ptr::null_mut()); |
169 | |
170 | v_ptr |
171 | } |
172 | } |
173 | } |
174 | |
175 | #[doc(hidden)] |
176 | impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::translate::ToGlibContainerFromSlice<'a, *const *const $ffi_name> for $name $(<$($generic),+>)? { |
177 | type Storage = (std::marker::PhantomData<&'a [Self]>, Option<Vec<*const $ffi_name>>); |
178 | |
179 | fn to_glib_none_from_slice(t: &'a [Self]) -> (*const *const $ffi_name, Self::Storage) { |
180 | let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *const $ffi_name>::to_glib_none_from_slice(t); |
181 | (ptr as *const *const $ffi_name, stash) |
182 | } |
183 | |
184 | fn to_glib_container_from_slice(_: &'a [Self]) -> (*const *const $ffi_name, Self::Storage) { |
185 | // Can't have consumer free a *const pointer |
186 | unimplemented!() |
187 | } |
188 | |
189 | fn to_glib_full_from_slice(_: &[Self]) -> *const *const $ffi_name { |
190 | // Can't have consumer free a *const pointer |
191 | unimplemented!() |
192 | } |
193 | } |
194 | |
195 | #[doc(hidden)] |
196 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name $(<$($generic),+>)? { |
197 | #[inline] |
198 | unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self { |
199 | Self { |
200 | inner: $crate::translate::from_glib_none(ptr), |
201 | } |
202 | } |
203 | } |
204 | |
205 | #[doc(hidden)] |
206 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name $(<$($generic),+>)? { |
207 | #[inline] |
208 | unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self { |
209 | Self { |
210 | inner: $crate::translate::from_glib_none(ptr), |
211 | } |
212 | } |
213 | } |
214 | |
215 | #[doc(hidden)] |
216 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name $(<$($generic),+>)? { |
217 | #[inline] |
218 | unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self { |
219 | Self { |
220 | inner: $crate::translate::from_glib_full(ptr), |
221 | } |
222 | } |
223 | } |
224 | |
225 | #[doc(hidden)] |
226 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrFull<*const $ffi_name> for $name $(<$($generic),+>)? { |
227 | #[inline] |
228 | unsafe fn from_glib_full(ptr: *const $ffi_name) -> Self { |
229 | Self { |
230 | inner: $crate::translate::from_glib_full(ptr), |
231 | } |
232 | } |
233 | } |
234 | |
235 | #[doc(hidden)] |
236 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name $(<$($generic),+>)? { |
237 | #[inline] |
238 | unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> $crate::translate::Borrowed<Self> { |
239 | $crate::translate::Borrowed::new( |
240 | Self { |
241 | inner: $crate::translate::from_glib_borrow::<_, $crate::boxed::Boxed<_, _>>(ptr).into_inner(), |
242 | } |
243 | ) |
244 | } |
245 | } |
246 | |
247 | #[doc(hidden)] |
248 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name $(<$($generic),+>)? { |
249 | #[inline] |
250 | unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> $crate::translate::Borrowed<Self> { |
251 | $crate::translate::from_glib_borrow::<_, Self>(ptr as *mut $ffi_name) |
252 | } |
253 | } |
254 | |
255 | #[doc(hidden)] |
256 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? { |
257 | unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> { |
258 | if num == 0 || ptr.is_null() { |
259 | return Vec::new(); |
260 | } |
261 | |
262 | let mut res = Vec::<Self>::with_capacity(num); |
263 | let res_ptr = res.as_mut_ptr(); |
264 | for i in 0..num { |
265 | ::std::ptr::write(res_ptr.add(i), $crate::translate::from_glib_none(std::ptr::read(ptr.add(i)))); |
266 | } |
267 | res.set_len(num); |
268 | res |
269 | } |
270 | |
271 | unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> { |
272 | let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num); |
273 | $crate::ffi::g_free(ptr as *mut _); |
274 | res |
275 | } |
276 | |
277 | unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> { |
278 | if num == 0 || ptr.is_null() { |
279 | $crate::ffi::g_free(ptr as *mut _); |
280 | return Vec::new(); |
281 | } |
282 | |
283 | let mut res = Vec::with_capacity(num); |
284 | let res_ptr = res.as_mut_ptr(); |
285 | ::std::ptr::copy_nonoverlapping(ptr as *mut Self, res_ptr, num); |
286 | res.set_len(num); |
287 | $crate::ffi::g_free(ptr as *mut _); |
288 | res |
289 | } |
290 | } |
291 | |
292 | #[doc(hidden)] |
293 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name $(<$($generic),+>)? { |
294 | unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> { |
295 | $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr)) |
296 | } |
297 | |
298 | unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> { |
299 | $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr)) |
300 | } |
301 | |
302 | unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> { |
303 | $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr)) |
304 | } |
305 | } |
306 | #[doc(hidden)] |
307 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*mut $ffi_name> for $name $(<$($generic),+>)? { |
308 | #[inline] |
309 | unsafe fn into_glib_ptr(self) -> *mut $ffi_name { |
310 | let s = std::mem::ManuallyDrop::new(self); |
311 | $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *mut _ |
312 | } |
313 | } |
314 | |
315 | #[doc(hidden)] |
316 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::translate::IntoGlibPtr<*const $ffi_name> for $name $(<$($generic),+>)? { |
317 | #[inline] |
318 | unsafe fn into_glib_ptr(self) -> *const $ffi_name { |
319 | let s = std::mem::ManuallyDrop::new(self); |
320 | $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&*s).0 as *const _ |
321 | } |
322 | } |
323 | |
324 | }; |
325 | |
326 | (@value_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $ffi_name:ty) => { |
327 | }; |
328 | |
329 | (@value_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $ffi_name:ty, @type_ $get_type_expr:expr) => { |
330 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::StaticType for $name $(<$($generic),+>)? { |
331 | #[inline] |
332 | fn static_type() -> $crate::types::Type { |
333 | #[allow(unused_unsafe)] |
334 | #[allow(clippy::macro_metavars_in_unsafe)] |
335 | unsafe { $crate::translate::from_glib($get_type_expr) } |
336 | } |
337 | } |
338 | |
339 | #[doc(hidden)] |
340 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueType for $name $(<$($generic),+>)? { |
341 | type Type = Self; |
342 | } |
343 | |
344 | #[doc(hidden)] |
345 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ValueTypeOptional for $name $(<$($generic),+>)? { } |
346 | |
347 | #[doc(hidden)] |
348 | unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for $name $(<$($generic),+>)? { |
349 | type Checker = $crate::value::GenericValueTypeOrNoneChecker<Self>; |
350 | |
351 | #[inline] |
352 | unsafe fn from_value(value: &'a $crate::Value) -> Self { |
353 | let ptr = $crate::gobject_ffi::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0); |
354 | debug_assert!(!ptr.is_null()); |
355 | <Self as $crate::translate::FromGlibPtrFull<*mut $ffi_name>>::from_glib_full(ptr as *mut $ffi_name) |
356 | } |
357 | } |
358 | |
359 | #[doc(hidden)] |
360 | unsafe impl<'a $(, $($generic $(: $bound $(+ $bound2)*)?),+)?> $crate::value::FromValue<'a> for &'a $name $(<$($generic),+>)? { |
361 | type Checker = $crate::value::GenericValueTypeOrNoneChecker<Self>; |
362 | |
363 | #[inline] |
364 | unsafe fn from_value(value: &'a $crate::Value) -> Self { |
365 | let value = &*(value as *const $crate::Value as *const $crate::gobject_ffi::GValue); |
366 | <$name $(<$($generic),+>)?>::from_glib_ptr_borrow(&*(&value.data[0].v_pointer as *const $crate::ffi::gpointer as *const *mut $ffi_name)) |
367 | } |
368 | } |
369 | |
370 | #[doc(hidden)] |
371 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValue for $name $(<$($generic),+>)? { |
372 | #[inline] |
373 | fn to_value(&self) -> $crate::Value { |
374 | unsafe { |
375 | let mut value = $crate::Value::from_type_unchecked(<Self as $crate::prelude::StaticType>::static_type()); |
376 | $crate::gobject_ffi::g_value_take_boxed( |
377 | $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0, |
378 | $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_full(self) as *mut _, |
379 | ); |
380 | value |
381 | } |
382 | } |
383 | |
384 | #[inline] |
385 | fn value_type(&self) -> $crate::Type { |
386 | <Self as $crate::prelude::StaticType>::static_type() |
387 | } |
388 | } |
389 | |
390 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? std::convert::From<$name $(<$($generic),+>)?> for $crate::Value { |
391 | #[inline] |
392 | fn from(o: $name $(<$($generic),+>)?) -> Self { |
393 | unsafe { |
394 | let mut value = $crate::Value::from_type_unchecked(<$name $(<$($generic),+>)? as $crate::prelude::StaticType>::static_type()); |
395 | $crate::gobject_ffi::g_value_take_boxed( |
396 | $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0, |
397 | $crate::translate::IntoGlibPtr::<*mut $ffi_name>::into_glib_ptr(o) as *mut _, |
398 | ); |
399 | value |
400 | } |
401 | } |
402 | } |
403 | |
404 | #[doc(hidden)] |
405 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::value::ToValueOptional for $name $(<$($generic),+>)? { |
406 | #[inline] |
407 | fn to_value_optional(s: Option<&Self>) -> $crate::Value { |
408 | let mut value = $crate::Value::for_value_type::<Self>(); |
409 | unsafe { |
410 | $crate::gobject_ffi::g_value_take_boxed( |
411 | $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0, |
412 | $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_full(&s) as *mut _, |
413 | ); |
414 | } |
415 | |
416 | value |
417 | } |
418 | } |
419 | |
420 | |
421 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::prelude::HasParamSpec for $name $(<$($generic),+>)? { |
422 | type ParamSpec = $crate::ParamSpecBoxed; |
423 | type SetValue = Self; |
424 | type BuilderFn = fn(&str) -> $crate::ParamSpecBoxedBuilder<Self>; |
425 | |
426 | fn param_spec_builder() -> Self::BuilderFn { |
427 | |name| Self::ParamSpec::builder(name) |
428 | } |
429 | } |
430 | }; |
431 | |
432 | (@memory_manager_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $ffi_name:ty, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr) => { |
433 | #[doc(hidden)] |
434 | impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::boxed::BoxedMemoryManager for $name $(<$($generic),+>)? { |
435 | type Target = $ffi_name; |
436 | |
437 | #[inline] |
438 | unsafe fn copy($copy_arg: *const Self::Target) -> *mut Self::Target { |
439 | $copy_expr |
440 | } |
441 | |
442 | #[inline] |
443 | #[allow(clippy::no_effect)] |
444 | unsafe fn free($free_arg: *mut Self::Target) { |
445 | $free_expr; |
446 | } |
447 | } |
448 | }; |
449 | } |
450 | |
451 | // The safety docs really belong in the wrapper!() macro for Boxed<T> |
452 | /// Memory management functions for a boxed type. |
453 | pub trait BoxedMemoryManager: 'static { |
454 | type Target; |
455 | |
456 | /// Makes a copy. |
457 | unsafe fn copy(ptr: *const Self::Target) -> *mut Self::Target; |
458 | /// Frees the object. |
459 | unsafe fn free(ptr: *mut Self::Target); |
460 | } |
461 | |
462 | /// Encapsulates memory management logic for boxed types. |
463 | #[repr (transparent)] |
464 | pub struct Boxed<T: 'static, MM: BoxedMemoryManager<Target = T>> { |
465 | inner: ptr::NonNull<T>, |
466 | _dummy: PhantomData<*mut MM>, |
467 | } |
468 | |
469 | impl<'a, T: 'static, MM: BoxedMemoryManager<Target = T>> ToGlibPtr<'a, *const T> for Boxed<T, MM> { |
470 | type Storage = PhantomData<&'a Self>; |
471 | |
472 | #[inline ] |
473 | fn to_glib_none(&'a self) -> Stash<'a, *const T, Self> { |
474 | let ptr: *mut T = self.inner.as_ptr(); |
475 | Stash(ptr, PhantomData) |
476 | } |
477 | |
478 | #[inline ] |
479 | fn to_glib_full(&self) -> *const T { |
480 | let ptr: *mut T = self.inner.as_ptr(); |
481 | unsafe { MM::copy(ptr) } |
482 | } |
483 | } |
484 | |
485 | impl<'a, T: 'static, MM: BoxedMemoryManager<Target = T>> ToGlibPtrMut<'a, *mut T> for Boxed<T, MM> { |
486 | type Storage = PhantomData<&'a mut Self>; |
487 | |
488 | #[inline ] |
489 | fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut T, Self> { |
490 | let ptr: *mut T = self.inner.as_ptr(); |
491 | StashMut(ptr, PhantomData) |
492 | } |
493 | } |
494 | |
495 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrNone<*mut T> for Boxed<T, MM> { |
496 | #[inline ] |
497 | unsafe fn from_glib_none(ptr: *mut T) -> Self { |
498 | debug_assert!(!ptr.is_null()); |
499 | let ptr: *mut T = MM::copy(ptr); |
500 | from_glib_full(ptr) |
501 | } |
502 | } |
503 | |
504 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrNone<*const T> for Boxed<T, MM> { |
505 | #[inline ] |
506 | unsafe fn from_glib_none(ptr: *const T) -> Self { |
507 | debug_assert!(!ptr.is_null()); |
508 | let ptr: *mut T = MM::copy(ptr); |
509 | from_glib_full(ptr) |
510 | } |
511 | } |
512 | |
513 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrFull<*mut T> for Boxed<T, MM> { |
514 | #[inline ] |
515 | unsafe fn from_glib_full(ptr: *mut T) -> Self { |
516 | debug_assert!(!ptr.is_null()); |
517 | Self { |
518 | inner: ptr::NonNull::new_unchecked(ptr), |
519 | _dummy: PhantomData, |
520 | } |
521 | } |
522 | } |
523 | |
524 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrFull<*const T> for Boxed<T, MM> { |
525 | #[inline ] |
526 | unsafe fn from_glib_full(ptr: *const T) -> Self { |
527 | debug_assert!(!ptr.is_null()); |
528 | Self { |
529 | inner: ptr::NonNull::new_unchecked(ptr as *mut T), |
530 | _dummy: PhantomData, |
531 | } |
532 | } |
533 | } |
534 | |
535 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrBorrow<*mut T> for Boxed<T, MM> { |
536 | #[inline ] |
537 | unsafe fn from_glib_borrow(ptr: *mut T) -> Borrowed<Self> { |
538 | debug_assert!(!ptr.is_null()); |
539 | Borrowed::new(Self { |
540 | inner: ptr::NonNull::new_unchecked(ptr), |
541 | _dummy: PhantomData, |
542 | }) |
543 | } |
544 | } |
545 | |
546 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> Drop for Boxed<T, MM> { |
547 | #[inline ] |
548 | fn drop(&mut self) { |
549 | unsafe { |
550 | MM::free(self.inner.as_ptr()); |
551 | } |
552 | } |
553 | } |
554 | |
555 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> fmt::Debug for Boxed<T, MM> { |
556 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
557 | f.debug_struct("Boxed" ).field(name:"inner" , &self.inner).finish() |
558 | } |
559 | } |
560 | |
561 | impl<T, MM: BoxedMemoryManager<Target = T>> PartialOrd for Boxed<T, MM> { |
562 | #[inline ] |
563 | fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { |
564 | Some(self.cmp(other)) |
565 | } |
566 | } |
567 | |
568 | impl<T, MM: BoxedMemoryManager<Target = T>> Ord for Boxed<T, MM> { |
569 | #[inline ] |
570 | fn cmp(&self, other: &Self) -> cmp::Ordering { |
571 | self.to_glib_none().0.cmp(&other.to_glib_none().0) |
572 | } |
573 | } |
574 | |
575 | impl<T, MM: BoxedMemoryManager<Target = T>> PartialEq for Boxed<T, MM> { |
576 | #[inline ] |
577 | fn eq(&self, other: &Self) -> bool { |
578 | self.to_glib_none().0 == other.to_glib_none().0 |
579 | } |
580 | } |
581 | |
582 | impl<T, MM: BoxedMemoryManager<Target = T>> Eq for Boxed<T, MM> {} |
583 | |
584 | impl<T, MM: BoxedMemoryManager<Target = T>> Hash for Boxed<T, MM> { |
585 | #[inline ] |
586 | fn hash<H>(&self, state: &mut H) |
587 | where |
588 | H: Hasher, |
589 | { |
590 | self.to_glib_none().0.hash(state) |
591 | } |
592 | } |
593 | |
594 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> Clone for Boxed<T, MM> { |
595 | #[inline ] |
596 | fn clone(&self) -> Self { |
597 | unsafe { from_glib_none(self.to_glib_none().0 as *mut T) } |
598 | } |
599 | } |
600 | |
601 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> Deref for Boxed<T, MM> { |
602 | type Target = T; |
603 | |
604 | #[inline ] |
605 | fn deref(&self) -> &T { |
606 | unsafe { |
607 | // This is safe because the pointer will remain valid while self is borrowed |
608 | &*self.to_glib_none().0 |
609 | } |
610 | } |
611 | } |
612 | |
613 | impl<T: 'static, MM: BoxedMemoryManager<Target = T>> DerefMut for Boxed<T, MM> { |
614 | #[inline ] |
615 | fn deref_mut(&mut self) -> &mut T { |
616 | unsafe { |
617 | // This is safe because the pointer will remain valid while self is borrowed |
618 | &mut *self.to_glib_none_mut().0 |
619 | } |
620 | } |
621 | } |
622 | |