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}