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 } } }