Skip to main content

samp_sdk/
exports.rs

1//! Typed access to the `amx_*` functions exported by the server.
2//!
3//! The server exposes `amx_Exports` (passed in `Load()`) as a flat table of
4//! pointers, indexed by the values of [`Exports`]. Each function has a
5//! zero-sized marker type (generated by `impl_export!`) that carries the
6//! corresponding offset in [`Export::OFFSET`] and the function type in [`Export::Output`].
7//!
8//! Typical usage: `Exec::from_table(fn_table)` returns the typed pointer.
9//! Resolving on demand avoids storing all 44 pointers in [`crate::amx::Amx`].
10
11use crate::raw::functions;
12
13macro_rules! impl_export {
14    ($name:ident) => {
15        pub struct $name;
16
17        impl Export for $name {
18            type Output = functions::$name;
19            const OFFSET: isize = Exports::$name as isize;
20
21            #[inline(always)]
22            fn from_table(fn_table: usize) -> Self::Output {
23                assert!(fn_table != 0, "from_table() received null fn_table");
24                let table = fn_table as *const usize;
25
26                unsafe {
27                    let ptr = table.offset(Self::OFFSET);
28                    assert!(
29                        ptr.read() != 0,
30                        "from_table() function at offset {} is null",
31                        Self::OFFSET
32                    );
33                    ptr.cast::<Self::Output>().read()
34                }
35            }
36        }
37    };
38}
39
40/// Retrieves a typed pointer from the `amx_Exports` table.
41pub trait Export {
42    /// Type of the exported function — alias declared in [`crate::raw::functions`].
43    type Output;
44
45    /// Offset of this function in the table. Values correspond 1:1 to [`Exports`].
46    const OFFSET: isize;
47
48    /// Reads the pointer at offset `OFFSET` of the `fn_table` table.
49    ///
50    /// # Panics
51    /// In debug mode, panics if `fn_table` is null or if the read pointer is
52    /// null (indicates a non-conforming server or a corrupted table).
53    fn from_table(fn_table: usize) -> Self::Output;
54}
55
56impl_export!(Align16);
57impl_export!(Align32);
58impl_export!(Allot);
59impl_export!(Callback);
60impl_export!(Cleanup);
61impl_export!(Clone);
62impl_export!(Exec);
63impl_export!(FindNative);
64impl_export!(FindPublic);
65impl_export!(FindPubVar);
66impl_export!(FindTagId);
67impl_export!(Flags);
68impl_export!(GetAddr);
69impl_export!(GetNative);
70impl_export!(GetPublic);
71impl_export!(GetPubVar);
72impl_export!(GetString);
73impl_export!(GetTag);
74impl_export!(GetUserData);
75impl_export!(Init);
76impl_export!(InitJIT);
77impl_export!(MemInfo);
78impl_export!(NameLength);
79impl_export!(NativeInfo);
80impl_export!(NumNatives);
81impl_export!(NumPublics);
82impl_export!(NumPubVars);
83impl_export!(NumTags);
84impl_export!(Push);
85impl_export!(PushArray);
86impl_export!(PushString);
87impl_export!(RaiseError);
88impl_export!(Register);
89impl_export!(Release);
90impl_export!(SetCallback);
91impl_export!(SetDebugHook);
92impl_export!(SetString);
93impl_export!(SetUserData);
94impl_export!(StrLen);
95impl_export!(UTF8Check);
96impl_export!(UTF8Get);
97impl_export!(UTF8Len);
98impl_export!(UTF8Put);
99
100/// Indices of the `amx_*` functions in the server's `amx_Exports` table.
101///
102/// The order is fixed by the SA-MP ABI — do not reorder.
103#[derive(Debug, Clone, Copy, PartialEq)]
104pub enum Exports {
105    Align16 = 0,
106    Align32 = 1,
107    Align64 = 2,
108    Allot = 3,
109    Callback = 4,
110    Cleanup = 5,
111    Clone = 6,
112    Exec = 7,
113    FindNative = 8,
114    FindPublic = 9,
115    FindPubVar = 10,
116    FindTagId = 11,
117    Flags = 12,
118    GetAddr = 13,
119    GetNative = 14,
120    GetPublic = 15,
121    GetPubVar = 16,
122    GetString = 17,
123    GetTag = 18,
124    GetUserData = 19,
125    Init = 20,
126    InitJIT = 21,
127    MemInfo = 22,
128    NameLength = 23,
129    NativeInfo = 24,
130    NumNatives = 25,
131    NumPublics = 26,
132    NumPubVars = 27,
133    NumTags = 28,
134    Push = 29,
135    PushArray = 30,
136    PushString = 31,
137    RaiseError = 32,
138    Register = 33,
139    Release = 34,
140    SetCallback = 35,
141    SetDebugHook = 36,
142    SetString = 37,
143    SetUserData = 38,
144    StrLen = 39,
145    UTF8Check = 40,
146    UTF8Get = 41,
147    UTF8Len = 42,
148    UTF8Put = 43,
149}
150
151impl From<Exports> for isize {
152    fn from(exports: Exports) -> isize {
153        exports as isize
154    }
155}