use std::num::NonZeroI32;
use crate::{
AsLua, LuaRead, LuaTable, Nil, Push, PushGuard, PushInto, PushOne, PushOneInto, ReadResult,
Void,
};
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AnyLuaString(pub Vec<u8>);
impl AnyLuaString {
pub fn as_bytes(&self) -> &[u8] {
self.0.as_slice()
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum AnyHashableLuaValue {
LuaString(String),
LuaAnyString(AnyLuaString),
LuaNumber(i32),
LuaBoolean(bool),
LuaArray(Vec<(AnyHashableLuaValue, AnyHashableLuaValue)>),
LuaNil,
LuaOther,
}
#[derive(Clone, Debug, PartialEq)]
pub enum AnyLuaValue {
LuaString(String),
LuaAnyString(AnyLuaString),
LuaNumber(f64),
LuaBoolean(bool),
LuaArray(Vec<(AnyLuaValue, AnyLuaValue)>),
LuaNil,
LuaOther,
}
macro_rules! impl_any_lua_value {
(@push $self:expr, $lua:expr, $push:ident) => {
Ok(match $self {
Self::LuaString(val) => val.$push($lua),
Self::LuaAnyString(val) => val.$push($lua),
Self::LuaNumber(val) => val.$push($lua),
Self::LuaBoolean(val) => val.$push($lua),
Self::LuaArray(val) => val.$push($lua),
Self::LuaNil => Nil.$push($lua),
Self::LuaOther => panic!("can't push a AnyLuaValue of type Other"),
})
};
($t:ty) => {
impl<L: AsLua> Push<L> for $t {
type Err = Void; #[inline]
fn push_to_lua(&self, lua: L) -> Result<PushGuard<L>, (Void, L)> {
impl_any_lua_value!(@push self, lua, push_no_err)
}
}
impl<L: AsLua> PushOne<L> for $t {}
impl<L: AsLua> PushInto<L> for $t {
type Err = Void; #[inline]
fn push_into_lua(self, lua: L) -> Result<PushGuard<L>, (Void, L)> {
impl_any_lua_value!(@push self, lua, push_into_no_err)
}
}
impl<L: AsLua> PushOneInto<L> for $t {}
impl<L: AsLua> LuaRead<L> for $t {
#[inline]
fn lua_read_at_position(lua: L, index: NonZeroI32) -> ReadResult<Self, L> {
let lua = match LuaRead::lua_read_at_position(lua, index) {
Ok(v) => return Ok(Self::LuaString(v)),
Err((lua, _)) => lua,
};
let lua = match LuaRead::lua_read_at_position(lua, index) {
Ok(v) => return Ok(Self::LuaAnyString(v)),
Err((lua, _)) => lua,
};
let lua = match LuaRead::lua_read_at_position(lua, index) {
Ok(v) => return Ok(Self::LuaNumber(v)),
Err((lua, _)) => lua,
};
let lua = match LuaRead::lua_read_at_position(lua, index) {
Ok(v) => return Ok(Self::LuaBoolean(v)),
Err((lua, _)) => lua,
};
let lua = match LuaRead::lua_read_at_position(lua, index) {
Ok(v) => return Ok(Self::LuaString(v)),
Err((lua, _)) => lua,
};
let lua = match LuaRead::lua_read_at_position(lua, index) {
Ok(v) => return Ok(Self::LuaAnyString(v)),
Err((lua, _)) => lua,
};
let lua = match Nil::lua_read_at_position(lua, index) {
Ok(Nil) => return Ok(Self::LuaNil),
Err((lua, _)) => lua,
};
let _ = match LuaTable::lua_read_at_position(lua.as_lua(), index) {
Ok(v) => return Ok(
Self::LuaArray(v.iter::<Self, Self>().flatten().collect())
),
Err((lua, _)) => lua,
};
Ok(Self::LuaOther)
}
}
}
}
impl_any_lua_value! {AnyLuaValue}
impl_any_lua_value! {AnyHashableLuaValue}