Skip to content
This repository has been archived by the owner on Jun 8, 2021. It is now read-only.

Commit

Permalink
Merge pull request #496 from sdroege/clear-boxed
Browse files Browse the repository at this point in the history
Add init/clear function for boxed types
  • Loading branch information
sdroege committed Jun 13, 2019
2 parents b52d708 + 7c647aa commit c5e2632
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 68 deletions.
203 changes: 135 additions & 68 deletions src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,69 +17,38 @@ use translate::*;
#[macro_export]
macro_rules! glib_boxed_wrapper {
([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
@free $free_arg:ident $free_expr:expr,
@free $free_arg:ident $free_expr:expr, @init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr,
@get_type $get_type_expr:expr) => {
glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
@free $free_arg $free_expr);

impl $crate::types::StaticType for $name {
fn static_type() -> $crate::types::Type {
#[allow(unused_unsafe)]
unsafe { $crate::translate::from_glib($get_type_expr) }
}
}

#[doc(hidden)]
impl<'a> $crate::value::FromValueOptional<'a> for $name {
unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
$crate::translate::from_glib_full($crate::gobject_sys::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0) as *mut $ffi_name)
}
}

#[doc(hidden)]
impl $crate::value::SetValue for $name {
unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
$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)
}
}
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr,
@init $init_arg $init_expr, @clear $clear_arg $clear_expr);
glib_boxed_wrapper!(@value_impl $name, $ffi_name, @get_type $get_type_expr);
};

#[doc(hidden)]
impl $crate::value::SetValueOptional for $name {
unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
$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)
}
}
([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
@free $free_arg:ident $free_expr:expr, @init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr) => {
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr,
@init $init_arg $init_expr, @clear $clear_arg $clear_expr);
};

([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
@free $free_arg:ident $free_expr:expr) => {
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr);
};

([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
@free $free_arg:ident $free_expr:expr, @get_type $get_type_expr:expr) => {
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr);
glib_boxed_wrapper!(@value_impl $name, $ffi_name, @get_type $get_type_expr);
};

(@generic_impl [$($attr:meta)*] $name:ident, $ffi_name:path) => {
$(#[$attr])*
#[derive(Clone)]
pub struct $name($crate::boxed::Boxed<$ffi_name, MemoryManager>);

#[doc(hidden)]
pub struct MemoryManager;

impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
#[inline]
unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
$copy_expr
}

#[inline]
unsafe fn free($free_arg: *mut $ffi_name) {
$free_expr
}
}

#[doc(hidden)]
impl $crate::translate::Uninitialized for $name {
#[inline]
unsafe fn uninitialized() -> Self {
$name($crate::boxed::Boxed::uninitialized())
}
}

#[doc(hidden)]
impl $crate::translate::GlibPtrDefault for $name {
type GlibType = *mut $ffi_name;
Expand Down Expand Up @@ -261,7 +230,100 @@ macro_rules! glib_boxed_wrapper {
$crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
}
}
}
};

(@value_impl $name:ident, $ffi_name:path, @get_type $get_type_expr:expr) => {
impl $crate::types::StaticType for $name {
fn static_type() -> $crate::types::Type {
#[allow(unused_unsafe)]
unsafe { $crate::translate::from_glib($get_type_expr) }
}
}

#[doc(hidden)]
impl<'a> $crate::value::FromValueOptional<'a> for $name {
unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
$crate::translate::from_glib_full($crate::gobject_sys::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0) as *mut $ffi_name)
}
}

#[doc(hidden)]
impl $crate::value::SetValue for $name {
unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
$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)
}
}

#[doc(hidden)]
impl $crate::value::SetValueOptional for $name {
unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
$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)
}
}
};

(@memory_manager_impl $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr) => {
#[doc(hidden)]
pub struct MemoryManager;

impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
#[inline]
unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
$copy_expr
}

#[inline]
unsafe fn free($free_arg: *mut $ffi_name) {
$free_expr
}

#[inline]
unsafe fn init(_: *mut $ffi_name) {
unimplemented!()
}

#[inline]
unsafe fn clear(_: *mut $ffi_name) {
unimplemented!()
}
}
};

(@memory_manager_impl $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr,
@init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr) => {
#[doc(hidden)]
pub struct MemoryManager;

impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
#[inline]
unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
$copy_expr
}

#[inline]
unsafe fn free($free_arg: *mut $ffi_name) {
$free_expr
}

#[inline]
unsafe fn init($init_arg: *mut $ffi_name) {
$init_expr
}

#[inline]
unsafe fn clear($clear_arg: *mut $ffi_name) {
$clear_expr
}
}

#[doc(hidden)]
impl $crate::translate::Uninitialized for $name {
#[inline]
unsafe fn uninitialized() -> Self {
$name($crate::boxed::Boxed::uninitialized())
}
}
};
}

enum AnyBox<T> {
Expand All @@ -287,6 +349,10 @@ pub trait BoxedMemoryManager<T>: 'static {
unsafe fn copy(ptr: *const T) -> *mut T;
/// Frees the object.
unsafe fn free(ptr: *mut T);
/// Initializes an already allocated object.
unsafe fn init(ptr: *mut T);
/// Clears and frees all memory of the object, but not the object itself.
unsafe fn clear(ptr: *mut T);
}

/// Encapsulates memory management logic for boxed types.
Expand All @@ -295,21 +361,16 @@ pub struct Boxed<T: 'static, MM: BoxedMemoryManager<T>> {
_dummy: PhantomData<MM>,
}

impl<T: 'static, MM: BoxedMemoryManager<T>> Boxed<T, MM> {
#[inline]
pub unsafe fn uninitialized() -> Self {
Boxed {
inner: AnyBox::Native(Box::new(mem::uninitialized())),
_dummy: PhantomData,
}
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> Uninitialized for Boxed<T, MM> {
#[inline]
unsafe fn uninitialized() -> Self {
Boxed {
inner: AnyBox::Native(Box::new(mem::uninitialized())),
inner: {
let mut inner = Box::<T>::new(mem::zeroed());
MM::init(&mut *inner);

AnyBox::Native(inner)
},
_dummy: PhantomData,
}
}
Expand Down Expand Up @@ -397,8 +458,14 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> Drop for Boxed<T, MM> {
#[inline]
fn drop(&mut self) {
unsafe {
if let AnyBox::ForeignOwned(ptr) = self.inner {
MM::free(ptr.as_ptr());
match self.inner {
AnyBox::ForeignOwned(ptr) => {
MM::free(ptr.as_ptr());
}
AnyBox::Native(ref mut box_) => {
MM::clear(&mut **box_);
}
_ => (),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ glib_wrapper! {
match fn {
copy => |ptr| gobject_sys::g_boxed_copy(glib_sys::g_date_get_type(), ptr as *const _) as *mut _,
free => |ptr| glib_sys::g_date_free(ptr),
init => |_ptr| (),
clear => |ptr| glib_sys::g_date_clear(ptr, 1),
get_type => || glib_sys::g_date_get_type(),
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,38 @@ macro_rules! glib_wrapper {
@free $free_arg $free_expr, @get_type $get_type_expr);
};

(
$(#[$attr:meta])*
pub struct $name:ident(Boxed<$ffi_name:path>);

match fn {
copy => |$copy_arg:ident| $copy_expr:expr,
free => |$free_arg:ident| $free_expr:expr,
init => |$init_arg:ident| $init_expr:expr,
clear => |$clear_arg:ident| $clear_expr:expr,
}
) => {
glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
@free $free_arg $free_expr, @init $init_arg $init_expr, @clear $clear_arg $clear_expr);
};

(
$(#[$attr:meta])*
pub struct $name:ident(Boxed<$ffi_name:path>);

match fn {
copy => |$copy_arg:ident| $copy_expr:expr,
free => |$free_arg:ident| $free_expr:expr,
init => |$init_arg:ident| $init_expr:expr,
clear => |$clear_arg:ident| $clear_expr:expr,
get_type => || $get_type_expr:expr,
}
) => {
glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
@free $free_arg $free_expr, @init $init_arg $init_expr, @clear $clear_arg $clear_expr,
@get_type $get_type_expr);
};

// Shared

(
Expand Down

0 comments on commit c5e2632

Please sign in to comment.