1use glib_sys::{g_array_free, g_free, g_malloc, gpointer, GArray};
4use std::marker::PhantomData;
5use std::mem::size_of;
6use std::ops::{Deref, DerefMut};
7
8use std::ptr::NonNull;
9
10#[repr(transparent)]
12pub struct GBox<T>(NonNull<T>);
13
14impl<T: Sized> GBox<T> {
15 pub fn new(val: T) -> Self {
16 unsafe {
17 let ptr = g_malloc(size_of::<T>());
18 if !ptr.is_null() {
19 *(ptr as *mut T) = val;
20 }
21 Self(NonNull::new(ptr as *mut T).unwrap())
22 }
23 }
24
25 pub fn as_ptr(&self) -> *const T {
26 self.0.as_ptr()
27 }
28}
29
30impl<T> Deref for GBox<T> {
31 type Target = T;
32
33 fn deref(&self) -> &Self::Target {
34 unsafe { self.0.as_ref() }
35 }
36}
37
38impl<T> DerefMut for GBox<T> {
39 fn deref_mut(&mut self) -> &mut Self::Target {
40 unsafe { self.0.as_mut() }
41 }
42}
43
44impl<T> Drop for GBox<T> {
45 fn drop(&mut self) {
46 unsafe {
47 g_free(self.0.as_ptr() as gpointer);
48 }
49 }
50}
51
52#[repr(transparent)]
53pub struct GBoxedSlice<T>(pub *mut GArray, PhantomData<T>);
54
55impl<T> GBoxedSlice<T> {
56 pub fn is_null(&self) -> bool {
57 self.0.is_null()
58 }
59}
60
61impl<T> Deref for GBoxedSlice<T> {
62 type Target = [T];
63
64 fn deref(&self) -> &Self::Target {
65 if self.0.is_null() {
66 panic!("Invalid GBoxedSlice: null");
67 } else {
68 let g_array = unsafe { &*self.0 };
69
70 if g_array.data.is_null() {
71 &[]
72 } else {
73 unsafe { std::slice::from_raw_parts(g_array.data as _, g_array.len as usize) }
74 }
75 }
76 }
77}
78
79impl<T> DerefMut for GBoxedSlice<T> {
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 if self.0.is_null() {
82 panic!("Invalid GBoxedSlice: null");
83 }
84 let g_array = unsafe { &mut *self.0 };
85
86 if g_array.data.is_null() {
87 &mut []
88 } else {
89 unsafe { std::slice::from_raw_parts_mut(g_array.data as *mut T, g_array.len as usize) }
90 }
91 }
92}
93
94impl<T> Drop for GBoxedSlice<T> {
95 fn drop(&mut self) {
96 if !self.0.is_null() {
97 unsafe {
98 g_array_free(self.0, true as _);
99 }
100 }
101 }
102}