tlua/
any.rs

1use std::num::NonZeroI32;
2
3use crate::{
4    AsLua, LuaRead, LuaTable, Nil, Push, PushGuard, PushInto, PushOne, PushOneInto, ReadResult,
5    Void,
6};
7
8#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub struct AnyLuaString(pub Vec<u8>);
10
11impl AnyLuaString {
12    pub fn as_bytes(&self) -> &[u8] {
13        self.0.as_slice()
14    }
15}
16
17/// Represents any value that can be stored by Lua
18#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
19pub enum AnyHashableLuaValue {
20    // TODO(gmoshkin): remove Lua prefix
21    LuaString(String),
22    LuaAnyString(AnyLuaString),
23    LuaNumber(i32),
24    // TODO(gmoshkin): True, False
25    LuaBoolean(bool),
26    LuaArray(Vec<(AnyHashableLuaValue, AnyHashableLuaValue)>),
27    LuaNil,
28
29    /// The "Other" element is (hopefully) temporary and will be replaced by "Function" and "Userdata".
30    /// A panic! will trigger if you try to push a Other.
31    LuaOther,
32}
33
34/// Represents any value that can be stored by Lua
35#[derive(Clone, Debug, PartialEq)]
36pub enum AnyLuaValue {
37    // TODO(gmoshkin): remove Lua prefix
38    LuaString(String),
39    LuaAnyString(AnyLuaString),
40    LuaNumber(f64),
41    // TODO(gmoshkin): True, False
42    LuaBoolean(bool),
43    LuaArray(Vec<(AnyLuaValue, AnyLuaValue)>),
44    LuaNil,
45
46    /// The "Other" element is (hopefully) temporary and will be replaced by "Function" and "Userdata".
47    /// A panic! will trigger if you try to push a Other.
48    LuaOther,
49}
50
51macro_rules! impl_any_lua_value {
52    (@push $self:expr, $lua:expr, $push:ident) => {
53        Ok(match $self {
54            Self::LuaString(val) => val.$push($lua),
55            Self::LuaAnyString(val) => val.$push($lua),
56            Self::LuaNumber(val) => val.$push($lua),
57            Self::LuaBoolean(val) => val.$push($lua),
58            Self::LuaArray(val) => val.$push($lua),
59            Self::LuaNil => Nil.$push($lua),
60            Self::LuaOther => panic!("can't push a AnyLuaValue of type Other"),
61        })
62    };
63    ($t:ty) => {
64        impl<L: AsLua> Push<L> for $t {
65            type Err = Void;      // TODO: use `!` instead (https://github.com/rust-lang/rust/issues/35121)
66
67            #[inline]
68            fn push_to_lua(&self, lua: L) -> Result<PushGuard<L>, (Void, L)> {
69                impl_any_lua_value!(@push self, lua, push_no_err)
70            }
71        }
72
73        impl<L: AsLua> PushOne<L> for $t {}
74
75        impl<L: AsLua> PushInto<L> for $t {
76            type Err = Void;      // TODO: use `!` instead (https://github.com/rust-lang/rust/issues/35121)
77
78            #[inline]
79            fn push_into_lua(self, lua: L) -> Result<PushGuard<L>, (Void, L)> {
80                impl_any_lua_value!(@push self, lua, push_into_no_err)
81            }
82        }
83
84        impl<L: AsLua> PushOneInto<L> for $t {}
85
86        impl<L: AsLua> LuaRead<L> for $t {
87            #[inline]
88            fn lua_read_at_position(lua: L, index: NonZeroI32) -> ReadResult<Self, L> {
89                let lua = match LuaRead::lua_read_at_position(lua, index) {
90                    Ok(v) => return Ok(Self::LuaString(v)),
91                    Err((lua, _)) => lua,
92                };
93
94                let lua = match LuaRead::lua_read_at_position(lua, index) {
95                    Ok(v) => return Ok(Self::LuaAnyString(v)),
96                    Err((lua, _)) => lua,
97                };
98
99                let lua = match LuaRead::lua_read_at_position(lua, index) {
100                    Ok(v) => return Ok(Self::LuaNumber(v)),
101                    Err((lua, _)) => lua,
102                };
103
104                let lua = match LuaRead::lua_read_at_position(lua, index) {
105                    Ok(v) => return Ok(Self::LuaBoolean(v)),
106                    Err((lua, _)) => lua,
107                };
108
109                let lua = match LuaRead::lua_read_at_position(lua, index) {
110                    Ok(v) => return Ok(Self::LuaString(v)),
111                    Err((lua, _)) => lua,
112                };
113
114                let lua = match LuaRead::lua_read_at_position(lua, index) {
115                    Ok(v) => return Ok(Self::LuaAnyString(v)),
116                    Err((lua, _)) => lua,
117                };
118
119                let lua = match Nil::lua_read_at_position(lua, index) {
120                    Ok(Nil) => return Ok(Self::LuaNil),
121                    Err((lua, _)) => lua,
122                };
123
124                let _ = match LuaTable::lua_read_at_position(lua.as_lua(), index) {
125                    Ok(v) => return Ok(
126                        Self::LuaArray(v.iter::<Self, Self>().flatten().collect())
127                    ),
128                    Err((lua, _)) => lua,
129                };
130
131                Ok(Self::LuaOther)
132            }
133        }
134    }
135}
136
137impl_any_lua_value! {AnyLuaValue}
138impl_any_lua_value! {AnyHashableLuaValue}