"fix" the destructor macro

long story short: compiler restrictions

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-02-15 15:48:17 +01:00
parent 6dd6718b6e
commit aabc6479bb
2 changed files with 47 additions and 33 deletions

View File

@ -29,5 +29,8 @@ mod export {
Ok(()) Ok(())
} }
perlmod::destructor! { Bless : CLASSNAME } #[export(name = "DESTROY")]
fn destroy(#[raw] this: Value) {
perlmod::destructor!(this, Bless : CLASSNAME);
}
} }

View File

@ -2,6 +2,10 @@
/// Create a standard destructor for a boxed type. /// Create a standard destructor for a boxed type.
/// ///
/// Due to compiler restrictions, the function itself needs to be written manually, only the
/// contents can be generated using this macro. This also means that the `this` parameter needs to
/// be passed to the macro.
///
/// For safety it is recommended to pass the package name to the macro in order for the generated /// For safety it is recommended to pass the package name to the macro in order for the generated
/// code to also guard against values not blessed into the package. /// code to also guard against values not blessed into the package.
/// ///
@ -9,22 +13,34 @@
/// ///
/// Usage: /// Usage:
/// ```ignore /// ```ignore
/// #[export(name = "DESTROY")]
/// fn destroy(#[raw] this: Value) {
/// // complete: /// // complete:
/// destructor!(MyType : "My::RS::Package" => { /// destructor!(this, MyType : "My::RS::Package" => {
/// Err(err) => { eprintln!("DESTROY called with invalid pointer: {}", err); } /// Err(err) => { eprintln!("DESTROY called with invalid pointer: {}", err); }
/// }); /// });
/// }
/// ///
/// #[export(name = "DESTROY")]
/// fn destroy(#[raw] this: Value) {
/// // error case only /// // error case only
/// destructor!(MyType { /// destructor!(this, MyType {
/// Err(err) => { eprintln!("DESTROY called with invalid pointer: {}", err); } /// Err(err) => { eprintln!("DESTROY called with invalid pointer: {}", err); }
/// }); /// });
/// }
/// ///
/// #[export(name = "DESTROY")]
/// fn destroy(#[raw] this: Value) {
/// // simple case with default error case (which is the above example case) /// // simple case with default error case (which is the above example case)
/// // the class name can also reference a constant. /// // the class name can also reference a constant.
/// destructor!(MyType : CLASSNAME); /// destructor!(this, MyType : CLASSNAME);
/// }
/// ///
/// #[export(name = "DESTROY")]
/// fn destroy(#[raw] this: Value) {
/// // simple less-safe case without checking the reference type. /// // simple less-safe case without checking the reference type.
/// destructor!(MyType); /// destructor!(this, MyType);
/// }
/// ``` /// ```
/// ///
/// The generated code looks like this: /// The generated code looks like this:
@ -45,9 +61,9 @@
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! destructor { macro_rules! destructor {
($ty:ty : $package:expr) => { ($this:expr, $ty:ty : $package:expr) => {
$crate::destructor! { $crate::destructor! {
$ty : $package => { $this, $ty : $package => {
Err(err) => { Err(err) => {
eprintln!("DESTROY called with invalid pointer: {}", err); eprintln!("DESTROY called with invalid pointer: {}", err);
} }
@ -55,22 +71,20 @@ macro_rules! destructor {
} }
}; };
($ty:ty : $package:expr => { ($this:expr, $ty:ty : $package:expr => {
Err($errname:ident) => $on_err:expr Err($errname:ident) => $on_err:expr
}) => { }) => {
#[perlmod::export(name = "DESTROY")] match unsafe { $this.from_blessed_box::<$ty>($package) } {
fn destroy(#[raw] this: Value) {
match unsafe { this.from_blessed_box::<$ty>($package) } {
Ok(ptr) => { Ok(ptr) => {
let _ = unsafe { Box::<$ty>::from_raw(ptr as *const $ty as *mut $ty) }; let _ = unsafe { Box::<$ty>::from_raw(ptr as *const $ty as *mut $ty) };
} }
Err($errname) => $on_err, Err($errname) => $on_err,
} }
}
}; };
($ty:ty) => { ($this:expr, $ty:ty) => {
$crate::destructor! { $crate::destructor! {
$this,
$ty { $ty {
Err(err) => { Err(err) => {
eprintln!("DESTROY called with invalid pointer: {}", err); eprintln!("DESTROY called with invalid pointer: {}", err);
@ -79,17 +93,14 @@ macro_rules! destructor {
} }
}; };
($ty:ty { ($this:expr, $ty:ty {
Err($name:ident) => $on_err:expr Err($name:ident) => $on_err:expr
}) => { }) => {
#[perlmod::export(name = "DESTROY")] match unsafe { $this.from_ref_box::<$ty>() } {
fn destroy(#[raw] this: Value) {
match unsafe { this.from_ref_box::<$ty>() } {
Ok(ptr) => { Ok(ptr) => {
let _ = unsafe { Box::<Bless>::from_raw(ptr) }; let _ = unsafe { Box::<Bless>::from_raw(ptr) };
} }
Err($name) => $on_err, Err($name) => $on_err,
} }
}
}; };
} }