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