servicepoint-binding-c/src/macros.rs
Vinzenz Schroeter c65b735f57
Some checks failed
Rust / build-gnu-apt (pull_request) Successful in 2m4s
Rust / build-size-gnu-unstable (pull_request) Failing after 2m44s
generic wrap
2025-06-26 22:36:57 +02:00

324 lines
11 KiB
Rust

macro_rules! derive_free {
($typ:ident) => {
::paste::paste! {
$crate::macros::wrap_method!($typ;
#[doc = "Deallocates a [`" $typ "`] instance."]
#[allow(dropping_copy_types)]
fn free(move instance) {
::std::mem::drop(instance)
};
);
}
};
}
macro_rules! derive_clone {
($object_type:ident) => {
::paste::paste! {
$crate::macros::wrap_method!($object_type;
#[doc = "Clones a [`" $object_type "`] instance."]
fn clone(ref instance) -> move ::core::ptr::NonNull<$object_type> {
instance.clone()
};
);
}
};
}
macro_rules! wrap_method {
(
$object_type:ident;
$(#[$meta:meta])+
fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?)
$(-> $return_modifier:ident $return_type:ty)?;
) => {
::paste::paste!{
$crate::macros::wrap_method!(
$object_type;
$(#[$meta])+
fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?)
$(-> $return_modifier $return_type)? {
$instance.$function($($($param_name),*)?)
};
);
}
};
($object_type:ident;
$(#[$meta:meta])+
fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?)
$(-> $return_modifier:ident $return_type:ty)?
$impl:block;
) => {
paste::paste! {
$crate::macros::wrap_functions!([< $object_type:lower >];
#[doc = " Calls method [`servicepoint::" $object_type "::" $function "`]."]
///
$(#[$meta])*
fn $function(
$instance: $ref_or_mut ::core::ptr::NonNull<$object_type>
$(,$($param_name: $param_modifier $param_type),*)?
) $(-> $return_modifier $return_type)?
$impl;
);
}
};
}
macro_rules! wrap_methods {
(
$object_type:ident;
$(
$(#[$meta:meta])+
fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?)
$(-> $return_modifier:ident $return_type:ty)?
$($impl:block)?;
)+
) => {
paste::paste! {
$(
$crate::macros::wrap_method!($object_type;
$(#[$meta])*
fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?)
$(-> $return_modifier $return_type)?
$($impl)?;
);
)+
}
};
}
macro_rules! wrap_fields_accessor {
(get; $object_type:ident :: $prop_name:ident : $prop_type:ty) => {
paste::paste! {
$crate::macros::wrap_method! {$object_type;
#[doc = " Gets the value of field `" $prop_name
"` of the [`servicepoint::" $object_type "`]."]
fn [<get _ $prop_name>](ref instance) -> val $prop_type {
instance.$prop_name
};
}
}
};
(mut get; $object_type:ident :: $prop_name:ident : $prop_type:ty) => {
paste::paste! {
$crate::macros::wrap_method! {$object_type;
#[doc = " Gets a reference to the field `" $prop_name
"` of the [`servicepoint::" $object_type "`]."]
///
/// - The returned reference inherits the lifetime of object in which it is contained.
/// - The returned pointer may not be used in a function that consumes the instance, e.g. to create a command.
fn [<get _ $prop_name _mut>](mut instance) -> val ::core::ptr::NonNull<$prop_type> {
::core::ptr::NonNull::from(&mut instance.$prop_name)
};
}
}
};
(set; $object_type:ident :: $prop_name:ident : $prop_type:ty) => {
paste::paste! {
$crate::macros::wrap_method! {$object_type;
#[doc = " Sets the value of field `" $prop_name
"` of the [`servicepoint::" $object_type "`]."]
fn [<set _ $prop_name>](mut instance, value: val $prop_type) {
instance.$prop_name = value;
};
}
}
};
(move set; $object_type:ident :: $prop_name:ident : $prop_type:ty) => {
paste::paste! {
$crate::macros::wrap_method! {$object_type;
#[doc = " Sets the value of field `" $prop_name
"` of the [`servicepoint::" $object_type "`]."]
/// The provided value is moved into the instance, potentially invalidating previously taken references.
fn [<set _ $prop_name>](mut instance, value: move ::core::ptr::NonNull<$prop_type>) {
instance.$prop_name = value;
};
}
}
};
}
macro_rules! wrap_fields {
(
$object_type:ident;
$(
prop $prop_name:ident : $prop_type:ty { $($accessor:ident $($modifier:ident)?;)+ };
)+
) => {
$($(
::paste::paste!{
$crate::macros::wrap_fields_accessor! {
$($modifier)? $accessor;
$object_type :: $prop_name: $prop_type
}
}
)+)+
};
}
macro_rules! apply_param_modifier {
(move, $param_name:ident) => {
unsafe { $crate::mem::heap_remove($param_name) }
};
(val, $param_name:ident) => {
$param_name
};
(mut, $param_name:ident) => {
unsafe { (&mut *$param_name.as_ptr()) }
};
(ref, $param_name:ident) => {
unsafe { $param_name.as_ref() }
};
(slice, $param_name:ident) => {
unsafe { $param_name.as_slice() }
};
}
macro_rules! apply_return_modifier {
(val, $result:ident) => {
$result
};
(move, $result:ident) => {
$crate::mem::heap_move_nonnull($result)
};
(move_ok, $result:ident) => {
$crate::mem::heap_move_ok($result)
};
(move_some, $result:ident) => {
$crate::mem::heap_move_some($result)
};
(slice, $result:ident) => {
unsafe { ByteSlice::from_slice($result) }
};
}
macro_rules! wrap_function {
(
$module:ident;
$(#[$meta:meta])+
fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?)
$(-> $return_modifier:ident $return_type:ty)?
$block:block;
) => {
::paste::paste! {
$(#[$meta])+
#[doc = ""]
#[doc = " This function is part of the `" $module "` module."]
#[no_mangle]
pub unsafe extern "C" fn [< sp_ $module _ $function >](
$($param_name: $param_type),*
) $(-> $return_type)?
{
$(
let $param_name = $crate::macros::apply_param_modifier!($param_modifier, $param_name);
)*
let result = $block;
$(
let result = $crate::macros::apply_return_modifier!($return_modifier, result);
)?
result
}
}
};
}
macro_rules! wrap_functions {
(
$module:ident;
$(
$(#[$meta:meta])+
fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?)
$(-> $return_modifier:ident $return_type:ty)?
$block:block;
)+
) => {
::paste::paste! {
$(
$crate::macros::wrap_function!($module;
$(#[$meta])+
fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_modifier $return_type)?
$block;
);
)+
}
};
(
associate $object_type:ident;
$(
$(#[$meta:meta])+
fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?)
$(-> $return_modifier:ident $return_type:ty)?
$block:block;
)+
) => {
::paste::paste! {
$crate::macros::wrap_functions!{[< $object_type:lower >];
$(
$(#[$meta])+
fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_modifier $return_type)?
$block;
)+
}
}
};
}
macro_rules! wrap {
(
$object_type:ident {
$(
properties:
$(
prop $prop_name:ident : $prop_type:ty { $($accessor:ident $($modifier:ident)?;)+ };
)*
)?
$(
functions:
$(
$(#[$fn_meta:meta])+
fn $fn_name:ident($($fn_param_name:ident: $fn_param_modifier:ident $fn_param_type:ty),*$(,)?)
$(-> $fn_return_modifier:ident $fn_return_type:ty)?
$fn_block:block;
)*
)?
$(
methods:
$(
$(#[$method_meta:meta])+
fn $method_name:ident($method_instance_modifier:ident $method_instance:ident $(, $($method_param_name:ident: $method_param_modifier:ident $method_param_type:ty),*)?)
$(-> $method_return_modifier:ident $method_return_type:ty)?
$($method_impl:block)?;
)*
)?
}
) => {
$($(
$crate::macros::wrap_fields!($object_type;
prop $prop_name : $prop_type { $($accessor $($modifier)?;)+ };
);
)*)?
$($(
$crate::macros::wrap_functions!(associate $object_type;
$(#[$fn_meta])+
fn $fn_name($($fn_param_name: $fn_param_modifier $fn_param_type),*)
$(-> $fn_return_modifier $fn_return_type)?
$fn_block;
);
)*)?
$($(
$crate::macros::wrap_method!($object_type;
$(#[$method_meta])+
fn $method_name($method_instance_modifier $method_instance $(, $($method_param_name: $method_param_modifier $method_param_type),*)?)
$(-> $method_return_modifier $method_return_type)?
$($method_impl)?;
);
)*)?
};
}
pub(crate) use {
apply_param_modifier, apply_return_modifier, derive_clone, derive_free,
wrap, wrap_fields, wrap_fields_accessor, wrap_function, wrap_functions,
wrap_method, wrap_methods,
};