use crate::amx::Amx;
use crate::cell::AmxCell;
pub struct Args<'a> {
amx: &'a Amx,
params: *const i32,
offset: usize,
}
impl<'a> Args<'a> {
#[must_use]
pub fn new(amx: &'a Amx, params: *const i32) -> Args<'a> {
Args {
amx,
params,
offset: 0,
}
}
pub fn next_arg<T: AmxCell<'a> + 'a>(&mut self) -> Option<T> {
let result = self.get(self.offset);
self.offset += 1;
result
}
#[must_use]
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.params.add(offset + 1).read()).ok() }
}
pub fn reset(&mut self) {
self.offset = 0;
}
#[must_use]
pub fn count(&self) -> usize {
let raw = unsafe { self.params.read() };
if raw <= 0 {
return 0;
}
#[allow(clippy::cast_sign_loss)]
let count = (raw / 4) as usize;
count
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn count_with_zero_returns_zero() {
let data: [i32; 1] = [0];
let amx = Amx::new(std::ptr::null_mut(), 0);
let args = Args::new(&amx, data.as_ptr());
assert_eq!(args.count(), 0);
}
#[test]
fn count_with_negative_returns_zero() {
let data: [i32; 1] = [-8];
let amx = Amx::new(std::ptr::null_mut(), 0);
let args = Args::new(&amx, data.as_ptr());
assert_eq!(args.count(), 0);
}
#[test]
fn count_with_valid_args() {
let data: [i32; 4] = [12, 100, 200, 300];
let amx = Amx::new(std::ptr::null_mut(), 0);
let args = Args::new(&amx, data.as_ptr());
assert_eq!(args.count(), 3);
}
#[test]
fn get_out_of_bounds_returns_none() {
let data: [i32; 2] = [4, 42]; let amx = Amx::new(std::ptr::null_mut(), 0);
let args = Args::new(&amx, data.as_ptr());
assert!(args.get::<crate::cell::Ref<i32>>(1).is_none());
}
#[test]
fn reset_resets_offset() {
let data: [i32; 1] = [0];
let amx = Amx::new(std::ptr::null_mut(), 0);
let mut args = Args::new(&amx, data.as_ptr());
args.offset = 5;
args.reset();
assert_eq!(args.offset, 0);
}
}