Skip to main content

samp_sdk/
macros.rs

1/// Executes an AMX public function by name.
2///
3/// Resolves the function index via `amx_FindPublic` and pushes the arguments
4/// before invoking `amx_Exec`. Types implementing `AmxCell` are passed directly.
5/// Rust strings and slices use alternative syntax (`expr => string` / `=> array`):
6/// the macro allocates memory on the AMX heap, copies the content, and releases
7/// everything when the `Allocator` goes out of scope.
8///
9/// # Examples
10///
11/// Without arguments:
12/// ```rust,no_run
13/// use samp_sdk::exec_public;
14/// # use samp_sdk::amx::Amx;
15/// # let amx_owned = Amx::new(std::ptr::null_mut(), 0);
16/// # let amx = &amx_owned;
17/// exec_public!(amx, "SomePublicFunction");
18/// ```
19///
20/// With arguments that implement `AmxCell`:
21/// ```rust,no_run
22/// use samp_sdk::exec_public;
23/// # use samp_sdk::amx::Amx;
24/// # use samp_sdk::cell::{AmxString, UnsizedBuffer, Ref};
25/// # use samp_sdk::error::AmxResult;
26/// // native CallPublic(const publicname[], const string[], buffer[], length, &someref);
27/// fn call_public(amx: &Amx, pub_name: AmxString, string: AmxString, buffer: UnsizedBuffer, size: usize, reference: Ref<usize>) -> AmxResult<bool> {
28///     let buffer = buffer.into_sized_buffer(size);
29///     let public_name = pub_name.to_string();
30///     exec_public!(amx, &public_name, string, buffer, reference);
31///     Ok(true)
32/// }
33/// ```
34///
35/// With Rust strings and slices (automatic allocation on the AMX heap):
36/// ```rust,no_run
37/// use samp_sdk::exec_public;
38/// # use samp_sdk::amx::Amx;
39/// # use samp_sdk::cell::{AmxString, UnsizedBuffer, Ref};
40/// # use samp_sdk::error::AmxResult;
41/// // native CallPublic(const publicname[], const string[]);
42/// fn call_public(amx: &Amx, pub_name: AmxString, string: AmxString) -> AmxResult<bool> {
43///     let public_name = pub_name.to_string();
44///     let rust_string = "hello!";
45///     let owned_string = "another hello!".to_string();
46///     let rust_array = vec![1, 2, 3, 4, 5];
47///     exec_public!(amx, &public_name, string, rust_string => string, &owned_string => string, &rust_array => array);
48///     Ok(true)
49/// }
50/// ```
51#[macro_export]
52macro_rules! exec_public {
53    ($amx:expr, $pubname:expr) => {
54        $amx.find_public($pubname)
55            .and_then(|idx| $amx.exec(idx))
56    };
57
58    (@ $amx:expr, $al:ident, $arg:expr) => {
59        $amx.push($arg)?;
60    };
61
62    (@ $amx:expr, $al:ident, $arg:expr, $($tail:tt)+) => {
63        exec_public!(@ $amx, $al, $($tail)+);
64        exec_public!(@ $amx, $al, $arg);
65    };
66
67    (@ $amx:expr, $al:ident, $arg:expr => string) => {
68        let string = $al.allot_string($arg)?;
69        $amx.push(string)?;
70    };
71
72    (@ $amx:expr, $al:ident, $arg:expr => string, $($tail:tt)+) => {
73        exec_public!(@ $amx, $al, $($tail)+);
74        exec_public!(@ $amx, $al, $arg => string);
75    };
76
77    (@ $amx:expr, $al:ident, $arg:expr => array) => {
78        let array = $al.allot_array($arg)?;
79        $amx.push(array)?;
80    };
81
82    (@ $amx:expr, $al:ident, $arg:expr => array, $($tail:tt)+) => {
83        exec_public!(@ $amx, $al, $($tail)+);
84        exec_public!(@ $amx, $al, $arg => array);
85    };
86
87    ($amx:expr, $pubname:expr, $($args:tt)+) => {
88        {
89            let allocator = $amx.allocator();
90            $amx.find_public($pubname)
91                .and_then(|idx| {
92                    exec_public!(@ $amx, allocator, $($args)+);
93                    $amx.exec(idx)
94                })
95        }
96    };
97}