use crate::amx::{Allocator, Amx};
use crate::cell::{AmxPrimitive, AmxString, Buffer, Ref};
use crate::error::AmxResult;
pub trait PublicArg<'amx> {
fn push_to(self, amx: &'amx Amx, allocator: &Allocator<'amx>) -> AmxResult<()>;
}
macro_rules! impl_cell_arg {
($($type:ty),* $(,)?) => {
$(
impl<'amx> PublicArg<'amx> for $type {
#[inline]
fn push_to(self, amx: &'amx Amx, _allocator: &Allocator<'amx>) -> AmxResult<()> {
amx.push(self)
}
}
)*
};
}
impl_cell_arg!(i8, u8, i16, u16, i32, u32, usize, isize, f32, bool);
impl<'amx> PublicArg<'amx> for AmxString<'amx> {
#[inline]
fn push_to(self, amx: &'amx Amx, _allocator: &Allocator<'amx>) -> AmxResult<()> {
amx.push(self)
}
}
impl<'amx> PublicArg<'amx> for Buffer<'amx> {
#[inline]
fn push_to(self, amx: &'amx Amx, _allocator: &Allocator<'amx>) -> AmxResult<()> {
amx.push(self)
}
}
impl<'amx, T: AmxPrimitive> PublicArg<'amx> for Ref<'amx, T> {
#[inline]
fn push_to(self, amx: &'amx Amx, _allocator: &Allocator<'amx>) -> AmxResult<()> {
amx.push(self)
}
}
impl<'amx> PublicArg<'amx> for &str {
#[inline]
fn push_to(self, amx: &'amx Amx, allocator: &Allocator<'amx>) -> AmxResult<()> {
let string = allocator.allot_string(self)?;
amx.push(string)
}
}
impl<'amx> PublicArg<'amx> for &String {
#[inline]
fn push_to(self, amx: &'amx Amx, allocator: &Allocator<'amx>) -> AmxResult<()> {
self.as_str().push_to(amx, allocator)
}
}
impl<'amx> PublicArg<'amx> for &[i32] {
#[inline]
fn push_to(self, amx: &'amx Amx, allocator: &Allocator<'amx>) -> AmxResult<()> {
let array = allocator.allot_array(self)?;
amx.push(array)
}
}
impl<'amx> PublicArg<'amx> for &Vec<i32> {
#[inline]
fn push_to(self, amx: &'amx Amx, allocator: &Allocator<'amx>) -> AmxResult<()> {
self.as_slice().push_to(amx, allocator)
}
}
pub trait PublicArgs<'amx> {
fn push_all(self, amx: &'amx Amx, allocator: &Allocator<'amx>) -> AmxResult<()>;
}
impl PublicArgs<'_> for () {
#[inline]
fn push_all(self, _amx: &Amx, _allocator: &Allocator<'_>) -> AmxResult<()> {
Ok(())
}
}
macro_rules! impl_args_tuple {
($(($($name:ident),+)),* $(,)?) => {
$(
#[allow(non_snake_case)]
impl<'amx, $($name: PublicArg<'amx>),+> PublicArgs<'amx> for ($($name,)+) {
#[inline]
fn push_all(self, amx: &'amx Amx, allocator: &Allocator<'amx>) -> AmxResult<()> {
let ($($name,)+) = self;
impl_args_tuple!(@push amx, allocator, $($name),+);
Ok(())
}
}
)*
};
(@push $amx:ident, $al:ident, $head:ident) => {
$head.push_to($amx, $al)?;
};
(@push $amx:ident, $al:ident, $head:ident, $($tail:ident),+) => {
impl_args_tuple!(@push $amx, $al, $($tail),+);
$head.push_to($amx, $al)?;
};
}
impl_args_tuple!(
(A),
(A, B),
(A, B, C),
(A, B, C, D),
(A, B, C, D, E),
(A, B, C, D, E, F),
(A, B, C, D, E, F, G),
(A, B, C, D, E, F, G, H),
(A, B, C, D, E, F, G, H, I),
(A, B, C, D, E, F, G, H, I, J),
(A, B, C, D, E, F, G, H, I, J, K),
(A, B, C, D, E, F, G, H, I, J, K, L),
);