Skip to content

Commit d5dbc8e

Browse files
authored
Merge pull request #1122 from mbiggio/wip/biggio/borrow-boxed
Implement FromGlibPtrBorrow on boxed and shared-boxed types
2 parents 2b5eae4 + 5dafd0f commit d5dbc8e

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

glib-macros/src/boxed_derive.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,22 @@ pub fn impl_boxed(input: &syn::DeriveInput) -> TokenStream {
197197

198198
#impl_from_value
199199

200+
impl #crate_ident::translate::FromGlibPtrBorrow<*const #name> for #name {
201+
#[inline]
202+
unsafe fn from_glib_borrow(ptr: *const #name) -> #crate_ident::translate::Borrowed<Self> {
203+
#crate_ident::translate::FromGlibPtrBorrow::from_glib_borrow(ptr as *mut _)
204+
}
205+
}
206+
207+
impl #crate_ident::translate::FromGlibPtrBorrow<*mut #name> for #name {
208+
#[inline]
209+
unsafe fn from_glib_borrow(ptr: *mut #name) -> #crate_ident::translate::Borrowed<Self> {
210+
debug_assert!(!ptr.is_null());
211+
212+
#crate_ident::translate::Borrowed::new(std::ptr::read(ptr))
213+
}
214+
}
215+
200216
impl #crate_ident::translate::FromGlibPtrNone<*const #name> for #name {
201217
#[inline]
202218
unsafe fn from_glib_none(ptr: *const #name) -> Self {

glib-macros/src/shared_boxed_derive.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,26 @@ pub fn impl_shared_boxed(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
218218

219219
#impl_from_value
220220

221+
impl #crate_ident::translate::FromGlibPtrBorrow<*const #refcounted_type_prefix::InnerType> for #name {
222+
#[inline]
223+
unsafe fn from_glib_borrow(ptr: *const #refcounted_type_prefix::InnerType) -> #crate_ident::translate::Borrowed<Self> {
224+
debug_assert!(!ptr.is_null());
225+
226+
// from_raw is taking ownership of the raw pointer here, but wrapping its result
227+
// in Borrowed::new ensures that it won't be deallocated when it will go out of
228+
// scope, so the pointer will still be valid afterwards
229+
#crate_ident::translate::Borrowed::new(#name(#refcounted_type_prefix::from_raw(ptr)))
230+
}
231+
}
232+
233+
impl #crate_ident::translate::FromGlibPtrBorrow<*mut #refcounted_type_prefix::InnerType> for #name {
234+
#[inline]
235+
unsafe fn from_glib_borrow(ptr: *mut #refcounted_type_prefix::InnerType) -> #crate_ident::translate::Borrowed<Self> {
236+
#crate_ident::translate::FromGlibPtrBorrow::from_glib_borrow(ptr as *const _)
237+
}
238+
}
239+
240+
221241
impl #crate_ident::translate::FromGlibPtrNone<*const #refcounted_type_prefix::InnerType> for #name {
222242
#[inline]
223243
unsafe fn from_glib_none(ptr: *const #refcounted_type_prefix::InnerType) -> Self {

glib/src/subclass/boxed.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ mod test {
7171
// and that returns `glib` (and not `crate`) when called inside the glib crate
7272
use crate as glib;
7373
use crate::prelude::*;
74+
use crate::translate::{FromGlibPtrBorrow, FromGlibPtrFull, IntoGlibPtr};
7475

7576
#[derive(Clone, Debug, PartialEq, Eq, glib::Boxed)]
7677
#[boxed_type(name = "MyBoxed")]
@@ -90,4 +91,19 @@ mod test {
9091
let b2 = v.get::<&MyBoxed>().unwrap();
9192
assert_eq!(&b, b2);
9293
}
94+
95+
#[test]
96+
fn test_from_glib_borrow() {
97+
assert!(MyBoxed::static_type().is_valid());
98+
99+
let b = MyBoxed(String::from("abc"));
100+
let raw_ptr = unsafe { MyBoxed::into_glib_ptr(b) };
101+
102+
// test that the from_glib_borrow does not take ownership of the raw_ptr
103+
let _ = unsafe { MyBoxed::from_glib_borrow(raw_ptr) };
104+
105+
let new_b = unsafe { MyBoxed::from_glib_full(raw_ptr) };
106+
107+
assert_eq!(new_b.0, "abc".to_string());
108+
}
93109
}

glib/src/subclass/shared.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,44 @@ mod test {
252252
unsafe { <MySharedRc as SharedType>::RefCountedType::from_raw(inner_raw_ptr_clone) };
253253
assert_eq!(std::rc::Rc::strong_count(&b.0), 1);
254254
}
255+
256+
#[test]
257+
fn from_glib_borrow_arc() {
258+
assert_ne!(crate::Type::INVALID, MySharedRc::static_type());
259+
260+
let b = MySharedArc::from_refcounted(std::sync::Arc::new(MySharedInner {
261+
foo: String::from("abc"),
262+
}));
263+
264+
let inner_raw_ptr = std::sync::Arc::into_raw(b.clone().0);
265+
266+
assert_eq!(std::sync::Arc::strong_count(&b.0), 2);
267+
268+
unsafe {
269+
let _ = MySharedArc::from_glib_borrow(inner_raw_ptr);
270+
assert_eq!(std::sync::Arc::strong_count(&b.0), 2);
271+
}
272+
273+
assert_eq!(std::sync::Arc::strong_count(&b.0), 2);
274+
}
275+
276+
#[test]
277+
fn from_glib_borrow_rc() {
278+
assert_ne!(crate::Type::INVALID, MySharedRc::static_type());
279+
280+
let b = MySharedRc::from_refcounted(std::rc::Rc::new(MySharedInner {
281+
foo: String::from("abc"),
282+
}));
283+
284+
let inner_raw_ptr = std::rc::Rc::into_raw(b.clone().0);
285+
286+
assert_eq!(std::rc::Rc::strong_count(&b.0), 2);
287+
288+
unsafe {
289+
let _ = MySharedRc::from_glib_borrow(inner_raw_ptr);
290+
assert_eq!(std::rc::Rc::strong_count(&b.0), 2);
291+
}
292+
293+
assert_eq!(std::rc::Rc::strong_count(&b.0), 2);
294+
}
255295
}

0 commit comments

Comments
 (0)