pxl_rust/macros.rs
1//! Macros for PXL
2//!
3//! This module provides macros to simplify the usage of PXL in Rust,
4//! particularly for managing arguments and executing operations with variable argument lists.
5
6use crate::ffi::ArgInfo_t;
7use crate::ffi::ArgType;
8use crate::ffi::c_void;
9
10/// Creates an `ArgInfo_t` structure
11pub fn create_arg_info(is_pointer: bool, address: *const c_void, size: usize) -> ArgInfo_t {
12 let arg_type = if is_pointer {
13 ArgType::DeviceMemory
14 } else {
15 ArgType::Constant
16 };
17
18 let mut ret = ArgInfo_t {
19 arg_type,
20 address,
21 total_size: size,
22 };
23
24 if is_pointer {
25 unsafe {
26 std::ptr::copy_nonoverlapping(
27 address as *const u8,
28 &mut ret.address as *mut _ as *mut u8,
29 size,
30 );
31 }
32 }
33
34 ret
35}
36
37/// Converts a value to `ArgInfo_t` to pass to C++ PXL.
38pub fn get_arg_info<T>(val: &T) -> ArgInfo_t {
39 let type_name = std::any::type_name::<T>();
40 let is_pointer = type_name.starts_with('*');
41 // println!(" {}, is_ptr:{}", type_name, is_pointer);
42
43 create_arg_info(
44 is_pointer,
45 val as *const _ as *const c_void,
46 std::mem::size_of_val(val),
47 )
48}
49
50/// Executes a `Map` or compatible executor with a variable number of arguments.
51///
52/// This macro simplifies passing multiple arguments to the `execute` method
53/// by automatically converting them into a vector of `ArgInfo_t` using `get_arg_info`.
54///
55/// # Syntax
56/// ```ignore
57/// execute!(executor(val1, val2, ...));
58/// ```
59///
60/// # Arguments
61/// * `executor` - An instance of an object that implements `execute(&Vec<ArgInfo_t>) -> bool`.
62/// * `val1`, `val2`, ... - A variadic list of arguments passed to the executor. Each argument can be:
63/// - A scalar value (e.g., `i32`, `f32`, etc.), which is treated as `ArgType::Constant`
64/// - A device memory pointer which is allocated from `Context`, which is treated as `ArgType::DeviceMemory`.
65///
66/// # Returns
67/// * `bool` - Result of the executor's `execute` method.
68///
69/// # Safety
70/// * This macro assumes any pointer arguments are
71///
72/// # Example
73/// ```ignore
74/// let val: i32 = 42;
75/// let ptr: context.mem_alloc(1024) as *mut i32;
76/// let result = execute!(map(val, ptr));
77/// ```
78///
79/// # Caution
80/// * This macro does not validate the provided pointers.
81/// * If a pointer is not allocated from a `Context`, the `execute` method will return `false`.
82
83#[macro_export]
84macro_rules! execute {
85 ($executor:ident ($($val:expr),* $(,)?)) => {{
86 let args = vec![
87 $(
88 {
89 let arg_info = pxl::macros::get_arg_info(&$val);
90 // println!("{:?}", arg_info);
91 arg_info
92 }
93 ),*
94 ];
95 $executor.execute(&args)
96 }};
97}