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}