1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! Workaround to parse input of natives functions.
use crate::amx::Amx;
use crate::cell::AmxCell;
/// A wrapper of a list of arguments of a native function.
pub struct Args<'a> {
amx: &'a Amx,
args: *const i32,
offset: usize,
}
impl<'a> Args<'a> {
/// Creates a list from [`Amx`] and arguments.
///
/// # Example
/// ```
/// use samp_sdk::args::Args;
/// use samp_sdk::amx::Amx;
/// use samp_sdk::cell::AmxString;
/// # use samp_sdk::raw::types::AMX;
///
/// // native: RawNative(const say_that[]);
/// extern "C" fn raw_native(amx: *mut AMX, args: *mut i32) -> i32 {
/// # let amx_exports = 0;
/// // let amx_exports = ...;
/// let amx = Amx::new(amx, amx_exports);
/// let mut args = Args::new(&amx, args);
///
/// let say_what = match args.next::<AmxString>() {
/// Some(string) => string.to_string(),
/// None => {
/// println!("RawNative error: no argument");
/// return 0;
/// }
/// };
///
/// println!("RawNative: {}", say_what);
///
/// return 1;
/// }
/// ```
///
/// [`Amx`]: ../amx/struct.Amx.html
pub fn new(amx: &'a Amx, args: *const i32) -> Args<'a> {
Args {
amx,
args,
offset: 0,
}
}
/// Return the next argument in the list (like an iterator).
///
/// When there is no arguments left returns `None`.
pub fn next<T: AmxCell<'a> + 'a>(&mut self) -> Option<T> {
let result = self.get(self.offset);
self.offset += 1;
result
}
/// Get an argument by position, if there is no argument in given location, returns `None`.
///
/// # Example
/// ```
/// use samp_sdk::args::Args;
/// use samp_sdk::amx::Amx;
/// use samp_sdk::cell::Ref;
/// # use samp_sdk::raw::types::AMX;
///
/// // native: NativeFn(player_id, &Float:health, &Float:armor);
/// extern "C" fn raw_native(amx: *mut AMX, args: *mut i32) -> i32 {
/// # let amx_exports = 0;
/// // let amx_exports = ...;
/// let amx = Amx::new(amx, amx_exports);
/// let args = Args::new(&amx, args);
///
/// // change only armor
/// args.get::<Ref<f32>>(2)
/// .map(|mut armor| *armor = 255.0);
///
/// return 1;
/// }
/// ```
pub fn get<T: AmxCell<'a> + 'a>(&self, offset: usize) -> Option<T> {
if offset > self.count() {
return None;
}
unsafe { T::from_raw(self.amx, self.args.add(offset + 1).read()).ok() }
}
/// Reset a read offset for [`next()`] method.
///
/// [`next()`]: #method.next
pub fn reset(&mut self) {
self.offset = 0;
}
/// Get count of arguments in the list.
pub fn count(&self) -> usize {
unsafe { (self.args.read() / 4) as usize }
}
}