Skip to content

Commit

Permalink
Implement FromGlibPtrBorrow on boxed and shared-boxed types
Browse files Browse the repository at this point in the history
  • Loading branch information
Matteo Biggio committed Jul 7, 2023
1 parent d8bf481 commit 5dafd0f
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 0 deletions.
16 changes: 16 additions & 0 deletions glib-macros/src/boxed_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,22 @@ pub fn impl_boxed(input: &syn::DeriveInput) -> TokenStream {

#impl_from_value

impl #crate_ident::translate::FromGlibPtrBorrow<*const #name> for #name {
#[inline]
unsafe fn from_glib_borrow(ptr: *const #name) -> #crate_ident::translate::Borrowed<Self> {
#crate_ident::translate::FromGlibPtrBorrow::from_glib_borrow(ptr as *mut _)
}
}

impl #crate_ident::translate::FromGlibPtrBorrow<*mut #name> for #name {
#[inline]
unsafe fn from_glib_borrow(ptr: *mut #name) -> #crate_ident::translate::Borrowed<Self> {
debug_assert!(!ptr.is_null());

#crate_ident::translate::Borrowed::new(std::ptr::read(ptr))
}
}

impl #crate_ident::translate::FromGlibPtrNone<*const #name> for #name {
#[inline]
unsafe fn from_glib_none(ptr: *const #name) -> Self {
Expand Down
20 changes: 20 additions & 0 deletions glib-macros/src/shared_boxed_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,26 @@ pub fn impl_shared_boxed(input: &syn::DeriveInput) -> proc_macro2::TokenStream {

#impl_from_value

impl #crate_ident::translate::FromGlibPtrBorrow<*const #refcounted_type_prefix::InnerType> for #name {
#[inline]
unsafe fn from_glib_borrow(ptr: *const #refcounted_type_prefix::InnerType) -> #crate_ident::translate::Borrowed<Self> {
debug_assert!(!ptr.is_null());

// from_raw is taking ownership of the raw pointer here, but wrapping its result
// in Borrowed::new ensures that it won't be deallocated when it will go out of
// scope, so the pointer will still be valid afterwards
#crate_ident::translate::Borrowed::new(#name(#refcounted_type_prefix::from_raw(ptr)))
}
}

impl #crate_ident::translate::FromGlibPtrBorrow<*mut #refcounted_type_prefix::InnerType> for #name {
#[inline]
unsafe fn from_glib_borrow(ptr: *mut #refcounted_type_prefix::InnerType) -> #crate_ident::translate::Borrowed<Self> {
#crate_ident::translate::FromGlibPtrBorrow::from_glib_borrow(ptr as *const _)
}
}


impl #crate_ident::translate::FromGlibPtrNone<*const #refcounted_type_prefix::InnerType> for #name {
#[inline]
unsafe fn from_glib_none(ptr: *const #refcounted_type_prefix::InnerType) -> Self {
Expand Down
16 changes: 16 additions & 0 deletions glib/src/subclass/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ mod test {
// and that returns `glib` (and not `crate`) when called inside the glib crate
use crate as glib;
use crate::prelude::*;
use crate::translate::{FromGlibPtrBorrow, FromGlibPtrFull, IntoGlibPtr};

#[derive(Clone, Debug, PartialEq, Eq, glib::Boxed)]
#[boxed_type(name = "MyBoxed")]
Expand All @@ -90,4 +91,19 @@ mod test {
let b2 = v.get::<&MyBoxed>().unwrap();
assert_eq!(&b, b2);
}

#[test]
fn test_from_glib_borrow() {
assert!(MyBoxed::static_type().is_valid());

let b = MyBoxed(String::from("abc"));
let raw_ptr = unsafe { MyBoxed::into_glib_ptr(b) };

// test that the from_glib_borrow does not take ownership of the raw_ptr
let _ = unsafe { MyBoxed::from_glib_borrow(raw_ptr) };

let new_b = unsafe { MyBoxed::from_glib_full(raw_ptr) };

assert_eq!(new_b.0, "abc".to_string());
}
}
40 changes: 40 additions & 0 deletions glib/src/subclass/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,44 @@ mod test {
unsafe { <MySharedRc as SharedType>::RefCountedType::from_raw(inner_raw_ptr_clone) };
assert_eq!(std::rc::Rc::strong_count(&b.0), 1);
}

#[test]
fn from_glib_borrow_arc() {
assert_ne!(crate::Type::INVALID, MySharedRc::static_type());

let b = MySharedArc::from_refcounted(std::sync::Arc::new(MySharedInner {
foo: String::from("abc"),
}));

let inner_raw_ptr = std::sync::Arc::into_raw(b.clone().0);

assert_eq!(std::sync::Arc::strong_count(&b.0), 2);

unsafe {
let _ = MySharedArc::from_glib_borrow(inner_raw_ptr);
assert_eq!(std::sync::Arc::strong_count(&b.0), 2);
}

assert_eq!(std::sync::Arc::strong_count(&b.0), 2);
}

#[test]
fn from_glib_borrow_rc() {
assert_ne!(crate::Type::INVALID, MySharedRc::static_type());

let b = MySharedRc::from_refcounted(std::rc::Rc::new(MySharedInner {
foo: String::from("abc"),
}));

let inner_raw_ptr = std::rc::Rc::into_raw(b.clone().0);

assert_eq!(std::rc::Rc::strong_count(&b.0), 2);

unsafe {
let _ = MySharedRc::from_glib_borrow(inner_raw_ptr);
assert_eq!(std::rc::Rc::strong_count(&b.0), 2);
}

assert_eq!(std::rc::Rc::strong_count(&b.0), 2);
}
}

0 comments on commit 5dafd0f

Please sign in to comment.