1use std::cmp;
8use std::fmt;
9use std::hash::{Hash, Hasher};
10use std::marker::PhantomData;
11use std::mem;
12use std::ops::{Deref, DerefMut};
13use std::ptr;
14use translate::*;
15
16#[macro_export]
18macro_rules! glib_boxed_wrapper {
19 ([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
20 @free $free_arg:ident $free_expr:expr, @init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr,
21 @get_type $get_type_expr:expr) => {
22 glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
23 glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr,
24 @init $init_arg $init_expr, @clear $clear_arg $clear_expr);
25 glib_boxed_wrapper!(@value_impl $name, $ffi_name, @get_type $get_type_expr);
26 };
27
28 ([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
29 @free $free_arg:ident $free_expr:expr, @init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr) => {
30 glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
31 glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr,
32 @init $init_arg $init_expr, @clear $clear_arg $clear_expr);
33 };
34
35 ([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
36 @free $free_arg:ident $free_expr:expr) => {
37 glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
38 glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr);
39 };
40
41 ([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
42 @free $free_arg:ident $free_expr:expr, @get_type $get_type_expr:expr) => {
43 glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
44 glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr);
45 glib_boxed_wrapper!(@value_impl $name, $ffi_name, @get_type $get_type_expr);
46 };
47
48 (@generic_impl [$($attr:meta)*] $name:ident, $ffi_name:path) => {
49 $(#[$attr])*
50 #[derive(Clone)]
51 pub struct $name($crate::boxed::Boxed<$ffi_name, MemoryManager>);
52 #[doc(hidden)]
53 impl $crate::translate::GlibPtrDefault for $name {
54 type GlibType = *mut $ffi_name;
55 }
56
57 #[doc(hidden)]
58 impl<'a> $crate::translate::ToGlibPtr<'a, *const $ffi_name> for $name {
59 type Storage = &'a $crate::boxed::Boxed<$ffi_name, MemoryManager>;
60
61 #[inline]
62 fn to_glib_none(&'a self) -> $crate::translate::Stash<'a, *const $ffi_name, Self> {
63 let stash = $crate::translate::ToGlibPtr::to_glib_none(&self.0);
64 $crate::translate::Stash(stash.0, stash.1)
65 }
66
67 #[inline]
68 fn to_glib_full(&self) -> *const $ffi_name {
69 $crate::translate::ToGlibPtr::to_glib_full(&self.0)
70 }
71 }
72
73 #[doc(hidden)]
74 impl<'a> $crate::translate::ToGlibPtrMut<'a, *mut $ffi_name> for $name {
75 type Storage = &'a mut $crate::boxed::Boxed<$ffi_name, MemoryManager>;
76
77 #[inline]
78 fn to_glib_none_mut(&'a mut self) -> $crate::translate::StashMut<'a, *mut $ffi_name, Self> {
79 let stash = $crate::translate::ToGlibPtrMut::to_glib_none_mut(&mut self.0);
80 $crate::translate::StashMut(stash.0, stash.1)
81 }
82 }
83
84 #[doc(hidden)]
85 impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *mut *const $ffi_name> for $name {
86 type Storage = (Vec<$crate::translate::Stash<'a, *const $ffi_name, $name>>, Option<Vec<*const $ffi_name>>);
87
88 fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut *const $ffi_name, Self::Storage) {
89 let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
90 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
91 v_ptr.push(::std::ptr::null_mut() as *const $ffi_name);
92
93 (v_ptr.as_ptr() as *mut *const $ffi_name, (v, Some(v_ptr)))
94 }
95
96 fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut *const $ffi_name, Self::Storage) {
97 let v: Vec<_> = t.iter().map(|s| $crate::translate::ToGlibPtr::to_glib_none(s)).collect();
98
99 let v_ptr = unsafe {
100 let v_ptr = $crate::glib_sys::g_malloc0(::std::mem::size_of::<*const $ffi_name>() * (t.len() + 1)) as *mut *const $ffi_name;
101
102 for (i, s) in v.iter().enumerate() {
103 ::std::ptr::write(v_ptr.add(i), s.0);
104 }
105
106 v_ptr
107 };
108
109 (v_ptr, (v, None))
110 }
111
112 fn to_glib_full_from_slice(t: &[$name]) -> *mut *const $ffi_name {
113 unsafe {
114 let v_ptr = $crate::glib_sys::g_malloc0(::std::mem::size_of::<*const $ffi_name>() * (t.len() + 1)) as *mut *const $ffi_name;
115
116 for (i, s) in t.iter().enumerate() {
117 ::std::ptr::write(v_ptr.add(i), $crate::translate::ToGlibPtr::to_glib_full(s));
118 }
119
120 v_ptr
121 }
122 }
123 }
124
125 #[doc(hidden)]
126 impl<'a> $crate::translate::ToGlibContainerFromSlice<'a, *const *const $ffi_name> for $name {
127 type Storage = (Vec<$crate::translate::Stash<'a, *const $ffi_name, $name>>, Option<Vec<*const $ffi_name>>);
128
129 fn to_glib_none_from_slice(t: &'a [$name]) -> (*const *const $ffi_name, Self::Storage) {
130 let (ptr, stash) = $crate::translate::ToGlibContainerFromSlice::<'a, *mut *const $ffi_name>::to_glib_none_from_slice(t);
131 (ptr as *const *const $ffi_name, stash)
132 }
133
134 fn to_glib_container_from_slice(_: &'a [$name]) -> (*const *const $ffi_name, Self::Storage) {
135 unimplemented!()
137 }
138
139 fn to_glib_full_from_slice(_: &[$name]) -> *const *const $ffi_name {
140 unimplemented!()
142 }
143 }
144
145 #[doc(hidden)]
146 impl $crate::translate::FromGlibPtrNone<*mut $ffi_name> for $name {
147 #[inline]
148 unsafe fn from_glib_none(ptr: *mut $ffi_name) -> Self {
149 $name($crate::translate::from_glib_none(ptr))
150 }
151 }
152
153 #[doc(hidden)]
154 impl $crate::translate::FromGlibPtrNone<*const $ffi_name> for $name {
155 #[inline]
156 unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self {
157 $name($crate::translate::from_glib_none(ptr))
158 }
159 }
160
161 #[doc(hidden)]
162 impl $crate::translate::FromGlibPtrFull<*mut $ffi_name> for $name {
163 #[inline]
164 unsafe fn from_glib_full(ptr: *mut $ffi_name) -> Self {
165 $name($crate::translate::from_glib_full(ptr))
166 }
167 }
168
169 #[doc(hidden)]
170 impl $crate::translate::FromGlibPtrBorrow<*mut $ffi_name> for $name {
171 #[inline]
172 unsafe fn from_glib_borrow(ptr: *mut $ffi_name) -> Self {
173 $name($crate::translate::from_glib_borrow(ptr))
174 }
175 }
176
177 #[doc(hidden)]
178 impl $crate::translate::FromGlibPtrBorrow<*const $ffi_name> for $name {
179 #[inline]
180 unsafe fn from_glib_borrow(ptr: *const $ffi_name) -> Self {
181 $crate::translate::from_glib_borrow(ptr as *mut $ffi_name)
182 }
183 }
184
185 #[doc(hidden)]
186 impl $crate::translate::FromGlibContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
187 unsafe fn from_glib_none_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
188 if num == 0 || ptr.is_null() {
189 return Vec::new();
190 }
191
192 let mut res = Vec::with_capacity(num);
193 for i in 0..num {
194 res.push($crate::translate::from_glib_none(::std::ptr::read(ptr.add(i))));
195 }
196 res
197 }
198
199 unsafe fn from_glib_container_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
200 let res = $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
201 $crate::glib_sys::g_free(ptr as *mut _);
202 res
203 }
204
205 unsafe fn from_glib_full_num_as_vec(ptr: *mut *mut $ffi_name, num: usize) -> Vec<Self> {
206 if num == 0 || ptr.is_null() {
207 return Vec::new();
208 }
209
210 let mut res = Vec::with_capacity(num);
211 for i in 0..num {
212 res.push($crate::translate::from_glib_full(::std::ptr::read(ptr.add(i))));
213 }
214 $crate::glib_sys::g_free(ptr as *mut _);
215 res
216 }
217 }
218
219 #[doc(hidden)]
220 impl $crate::translate::FromGlibPtrArrayContainerAsVec<*mut $ffi_name, *mut *mut $ffi_name> for $name {
221 unsafe fn from_glib_none_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
222 $crate::translate::FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
223 }
224
225 unsafe fn from_glib_container_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
226 $crate::translate::FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
227 }
228
229 unsafe fn from_glib_full_as_vec(ptr: *mut *mut $ffi_name) -> Vec<Self> {
230 $crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
231 }
232 }
233 };
234
235 (@value_impl $name:ident, $ffi_name:path, @get_type $get_type_expr:expr) => {
236 impl $crate::types::StaticType for $name {
237 fn static_type() -> $crate::types::Type {
238 #[allow(unused_unsafe)]
239 unsafe { $crate::translate::from_glib($get_type_expr) }
240 }
241 }
242
243 #[doc(hidden)]
244 impl<'a> $crate::value::FromValueOptional<'a> for $name {
245 unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
246 $crate::translate::from_glib_full($crate::gobject_sys::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0) as *mut $ffi_name)
247 }
248 }
249
250 #[doc(hidden)]
251 impl $crate::value::SetValue for $name {
252 unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
253 $crate::gobject_sys::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(this).0 as $crate::glib_sys::gpointer)
254 }
255 }
256
257 #[doc(hidden)]
258 impl $crate::value::SetValueOptional for $name {
259 unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
260 $crate::gobject_sys::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&this).0 as $crate::glib_sys::gpointer)
261 }
262 }
263 };
264
265 (@memory_manager_impl $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr) => {
266 #[doc(hidden)]
267 pub struct MemoryManager;
268
269 impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
270 #[inline]
271 unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
272 $copy_expr
273 }
274
275 #[inline]
276 unsafe fn free($free_arg: *mut $ffi_name) {
277 $free_expr
278 }
279
280 #[inline]
281 unsafe fn init(_: *mut $ffi_name) {
282 unimplemented!()
283 }
284
285 #[inline]
286 unsafe fn clear(_: *mut $ffi_name) {
287 unimplemented!()
288 }
289 }
290 };
291
292 (@memory_manager_impl $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr,
293 @init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr) => {
294 #[doc(hidden)]
295 pub struct MemoryManager;
296
297 impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
298 #[inline]
299 unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
300 $copy_expr
301 }
302
303 #[inline]
304 unsafe fn free($free_arg: *mut $ffi_name) {
305 $free_expr
306 }
307
308 #[inline]
309 unsafe fn init($init_arg: *mut $ffi_name) {
310 $init_expr
311 }
312
313 #[inline]
314 unsafe fn clear($clear_arg: *mut $ffi_name) {
315 $clear_expr
316 }
317 }
318
319 #[doc(hidden)]
320 impl $crate::translate::Uninitialized for $name {
321 #[inline]
322 unsafe fn uninitialized() -> Self {
323 $name($crate::boxed::Boxed::uninitialized())
324 }
325 }
326 };
327}
328
329enum AnyBox<T> {
330 Native(Box<T>),
331 ForeignOwned(ptr::NonNull<T>),
332 ForeignBorrowed(ptr::NonNull<T>),
333}
334
335impl<T> fmt::Debug for AnyBox<T> {
336 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
337 use self::AnyBox::*;
338 match *self {
339 Native(ref b) => f.debug_tuple("Native").field(&(&**b as *const T)).finish(),
340 ForeignOwned(ptr) => f.debug_tuple("ForeignOwned").field(&ptr).finish(),
341 ForeignBorrowed(ptr) => f.debug_tuple("ForeignBorrowed").field(&ptr).finish(),
342 }
343 }
344}
345
346pub trait BoxedMemoryManager<T>: 'static {
348 unsafe fn copy(ptr: *const T) -> *mut T;
350 unsafe fn free(ptr: *mut T);
352 unsafe fn init(ptr: *mut T);
354 unsafe fn clear(ptr: *mut T);
356}
357
358pub struct Boxed<T: 'static, MM: BoxedMemoryManager<T>> {
360 inner: AnyBox<T>,
361 _dummy: PhantomData<MM>,
362}
363
364impl<T: 'static, MM: BoxedMemoryManager<T>> Uninitialized for Boxed<T, MM> {
365 #[inline]
366 unsafe fn uninitialized() -> Self {
367 Boxed {
368 inner: {
369 let mut inner = Box::<T>::new(mem::zeroed());
370 MM::init(&mut *inner);
371
372 AnyBox::Native(inner)
373 },
374 _dummy: PhantomData,
375 }
376 }
377}
378
379impl<'a, T: 'static, MM: BoxedMemoryManager<T>> ToGlibPtr<'a, *const T> for Boxed<T, MM> {
380 type Storage = &'a Self;
381
382 #[inline]
383 fn to_glib_none(&'a self) -> Stash<'a, *const T, Self> {
384 use self::AnyBox::*;
385 let ptr = match self.inner {
386 Native(ref b) => &**b as *const T,
387 ForeignOwned(p) | ForeignBorrowed(p) => p.as_ptr(),
388 };
389 Stash(ptr, self)
390 }
391
392 #[inline]
393 fn to_glib_full(&self) -> *const T {
394 use self::AnyBox::*;
395 let ptr = match self.inner {
396 Native(ref b) => &**b as *const T,
397 ForeignOwned(p) | ForeignBorrowed(p) => p.as_ptr(),
398 };
399 unsafe { MM::copy(ptr) }
400 }
401}
402
403impl<'a, T: 'static, MM: BoxedMemoryManager<T>> ToGlibPtrMut<'a, *mut T> for Boxed<T, MM> {
404 type Storage = &'a mut Self;
405
406 #[inline]
407 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut T, Self> {
408 use self::AnyBox::*;
409 let ptr = match self.inner {
410 Native(ref mut b) => &mut **b as *mut T,
411 ForeignOwned(p) | ForeignBorrowed(p) => p.as_ptr(),
412 };
413 StashMut(ptr, self)
414 }
415}
416
417impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrNone<*mut T> for Boxed<T, MM> {
418 #[inline]
419 unsafe fn from_glib_none(ptr: *mut T) -> Self {
420 assert!(!ptr.is_null());
421 let ptr = MM::copy(ptr);
422 from_glib_full(ptr)
423 }
424}
425
426impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrNone<*const T> for Boxed<T, MM> {
427 #[inline]
428 unsafe fn from_glib_none(ptr: *const T) -> Self {
429 assert!(!ptr.is_null());
430 let ptr = MM::copy(ptr);
431 from_glib_full(ptr)
432 }
433}
434
435impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrFull<*mut T> for Boxed<T, MM> {
436 #[inline]
437 unsafe fn from_glib_full(ptr: *mut T) -> Self {
438 assert!(!ptr.is_null());
439 Boxed {
440 inner: AnyBox::ForeignOwned(ptr::NonNull::new_unchecked(ptr)),
441 _dummy: PhantomData,
442 }
443 }
444}
445
446impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrBorrow<*mut T> for Boxed<T, MM> {
447 #[inline]
448 unsafe fn from_glib_borrow(ptr: *mut T) -> Self {
449 assert!(!ptr.is_null());
450 Boxed {
451 inner: AnyBox::ForeignBorrowed(ptr::NonNull::new_unchecked(ptr)),
452 _dummy: PhantomData,
453 }
454 }
455}
456
457impl<T: 'static, MM: BoxedMemoryManager<T>> Drop for Boxed<T, MM> {
458 #[inline]
459 fn drop(&mut self) {
460 unsafe {
461 match self.inner {
462 AnyBox::ForeignOwned(ptr) => {
463 MM::free(ptr.as_ptr());
464 }
465 AnyBox::Native(ref mut box_) => {
466 MM::clear(&mut **box_);
467 }
468 _ => (),
469 }
470 }
471 }
472}
473
474impl<T: 'static, MM: BoxedMemoryManager<T>> fmt::Debug for Boxed<T, MM> {
475 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
476 f.debug_struct("Boxed").field("inner", &self.inner).finish()
477 }
478}
479
480impl<T, MM: BoxedMemoryManager<T>> PartialOrd for Boxed<T, MM> {
481 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
482 self.to_glib_none().0.partial_cmp(&other.to_glib_none().0)
483 }
484}
485
486impl<T, MM: BoxedMemoryManager<T>> Ord for Boxed<T, MM> {
487 fn cmp(&self, other: &Self) -> cmp::Ordering {
488 self.to_glib_none().0.cmp(&other.to_glib_none().0)
489 }
490}
491
492impl<T, MM: BoxedMemoryManager<T>> PartialEq for Boxed<T, MM> {
493 fn eq(&self, other: &Self) -> bool {
494 self.to_glib_none().0 == other.to_glib_none().0
495 }
496}
497
498impl<T, MM: BoxedMemoryManager<T>> Eq for Boxed<T, MM> {}
499
500impl<T, MM: BoxedMemoryManager<T>> Hash for Boxed<T, MM> {
501 fn hash<H>(&self, state: &mut H)
502 where
503 H: Hasher,
504 {
505 self.to_glib_none().0.hash(state)
506 }
507}
508
509impl<T: 'static, MM: BoxedMemoryManager<T>> Clone for Boxed<T, MM> {
510 #[inline]
511 fn clone(&self) -> Self {
512 unsafe { from_glib_none(self.to_glib_none().0 as *mut T) }
513 }
514}
515
516impl<T: 'static, MM: BoxedMemoryManager<T>> Deref for Boxed<T, MM> {
517 type Target = T;
518
519 fn deref(&self) -> &T {
520 unsafe {
521 &*self.to_glib_none().0
523 }
524 }
525}
526
527impl<T: 'static, MM: BoxedMemoryManager<T>> DerefMut for Boxed<T, MM> {
528 fn deref_mut(&mut self) -> &mut T {
529 unsafe {
530 &mut *self.to_glib_none_mut().0
532 }
533 }
534}