1use crate::number::LuaNumber;
2use crate::FloatType;
3use crate::IntType;
4use crate::LuaFunction;
5use crate::LuaString;
6use crate::LuaTable;
7use crate::LuaThread;
8use crate::RuntimeError;
9
10use std::cell::RefCell;
11use std::rc::Rc;
12
13#[derive(Debug, Clone)]
15pub enum RefOrValue {
16 Ref(Rc<RefCell<LuaValue>>),
17 Value(LuaValue),
18}
19impl Default for RefOrValue {
20 fn default() -> Self {
21 RefOrValue::Value(LuaValue::Nil)
22 }
23}
24
25#[derive(Debug, Clone)]
26pub enum LuaValue {
27 Nil,
28 Boolean(bool),
29 Number(LuaNumber),
30 String(LuaString),
31 Table(Rc<RefCell<LuaTable>>),
32 Function(Rc<RefCell<LuaFunction>>),
33 UserData(Rc<RefCell<LuaUserData>>),
34 Thread(Rc<RefCell<LuaThread>>),
35}
36impl std::hash::Hash for LuaValue {
37 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
38 std::mem::discriminant(self).hash(state);
39
40 match self {
41 LuaValue::Nil => {
42 unreachable!("hash for nil; this should be filtered out");
43 }
44 LuaValue::Boolean(b) => b.hash(state),
45 LuaValue::Number(n) => n.hash(state),
46 LuaValue::String(s) => s.hash(state),
47 LuaValue::Table(t) => Rc::as_ptr(t).hash(state),
48 LuaValue::Function(f) => Rc::as_ptr(f).hash(state),
49 LuaValue::UserData(u) => Rc::as_ptr(u).hash(state),
50 LuaValue::Thread(t) => Rc::as_ptr(t).hash(state),
51 }
52 }
53}
54impl std::cmp::PartialEq for LuaValue {
55 fn eq(&self, other: &Self) -> bool {
56 match (self, other) {
57 (LuaValue::Nil, LuaValue::Nil) => true,
58 (LuaValue::Boolean(a), LuaValue::Boolean(b)) => a == b,
59 (LuaValue::Number(a), LuaValue::Number(b)) => a == b,
60 (LuaValue::String(a), LuaValue::String(b)) => a == b,
61 (LuaValue::Table(a), LuaValue::Table(b)) => Rc::ptr_eq(a, b),
62 (LuaValue::Function(a), LuaValue::Function(b)) => Rc::ptr_eq(a, b),
63 (LuaValue::UserData(a), LuaValue::UserData(b)) => Rc::ptr_eq(a, b),
64 (LuaValue::Thread(a), LuaValue::Thread(b)) => Rc::ptr_eq(a, b),
65 _ => false,
66 }
67 }
68}
69impl std::cmp::Eq for LuaValue {}
70
71impl std::fmt::Display for LuaValue {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 match self {
74 LuaValue::Nil => write!(f, "nil"),
75 LuaValue::Boolean(b) => write!(f, "{}", b),
76 LuaValue::Number(n) => write!(f, "{}", n),
77 LuaValue::String(s) => write!(f, "{}", s),
78 LuaValue::Table(t) => {
79 write!(f, "table: {:p}", Rc::as_ptr(t))
80 }
81 LuaValue::Function(func) => write!(f, "function: {:p}", Rc::as_ptr(func)),
82 LuaValue::UserData(userdata) => write!(f, "userdata: {:p}", Rc::as_ptr(userdata)),
83 LuaValue::Thread(thread) => write!(f, "thread: {:p}", Rc::as_ptr(thread)),
84 }
85 }
86}
87
88impl LuaValue {
89 pub fn from_static_str(s: &'static str) -> Self {
91 LuaValue::String(LuaString::from_static_str(s))
92 }
93 pub fn from_static_slice(s: &'static [u8]) -> Self {
95 LuaValue::String(LuaString::from_static(s))
96 }
97
98 pub fn type_str(&self) -> &'static str {
100 match self {
101 LuaValue::Nil => "nil",
102 LuaValue::Boolean(_) => "boolean",
103 LuaValue::Number(_) => "number",
104 LuaValue::String(_) => "string",
105 LuaValue::Table(_) => "table",
106 LuaValue::Function(_) => "function",
107 LuaValue::Thread(_) => "thread",
108 LuaValue::UserData(_) => "userdata",
109 }
110 }
111
112 pub fn to_bool(&self) -> bool {
114 match self {
115 LuaValue::Nil | LuaValue::Boolean(false) => false,
116 _ => true,
117 }
118 }
119
120 pub fn try_to_int(&self) -> Result<IntType, RuntimeError> {
122 self.try_to_number()?.try_to_int()
123 }
124 pub fn try_to_number(&self) -> Result<LuaNumber, RuntimeError> {
126 match self {
127 LuaValue::Number(n) => Ok(*n),
128 LuaValue::String(s) => s.try_to_number(),
129 _ => Err(RuntimeError::Expected("number", Some(self.type_str()))),
130 }
131 }
132
133 pub fn is_nil(&self) -> bool {
134 match self {
135 LuaValue::Nil => true,
136 _ => false,
137 }
138 }
139 pub fn is_nan(&self) -> bool {
140 match self {
141 LuaValue::Number(n) => n.is_nan(),
142 _ => false,
143 }
144 }
145}
146
147impl Default for LuaValue {
148 fn default() -> Self {
149 LuaValue::Nil
150 }
151}
152
153impl From<()> for LuaValue {
154 fn from(_: ()) -> Self {
155 LuaValue::Nil
156 }
157}
158impl From<bool> for LuaValue {
159 fn from(b: bool) -> Self {
160 LuaValue::Boolean(b)
161 }
162}
163impl From<IntType> for LuaValue {
164 fn from(n: IntType) -> Self {
165 LuaValue::Number(LuaNumber::Int(n))
166 }
167}
168impl From<FloatType> for LuaValue {
169 fn from(n: FloatType) -> Self {
170 LuaValue::Number(LuaNumber::Float(n))
171 }
172}
173impl From<LuaNumber> for LuaValue {
174 fn from(n: LuaNumber) -> Self {
175 LuaValue::Number(n)
176 }
177}
178impl From<Vec<u8>> for LuaValue {
179 fn from(v: Vec<u8>) -> Self {
180 LuaValue::String(LuaString::from_vec(v))
181 }
182}
183impl From<String> for LuaValue {
184 fn from(s: String) -> Self {
185 LuaValue::String(LuaString::from_string(s))
186 }
187}
188impl From<&'static str> for LuaValue {
189 fn from(s: &'static str) -> Self {
190 LuaValue::String(LuaString::from_str(s))
191 }
192}
193impl From<&'static [u8]> for LuaValue {
194 fn from(s: &'static [u8]) -> Self {
195 LuaValue::String(LuaString::from_slice(s))
196 }
197}
198impl From<LuaString> for LuaValue {
199 fn from(s: LuaString) -> Self {
200 LuaValue::String(s)
201 }
202}
203impl From<LuaTable> for LuaValue {
204 fn from(t: LuaTable) -> Self {
205 LuaValue::Table(Rc::new(RefCell::new(t)))
206 }
207}
208impl From<LuaFunction> for LuaValue {
209 fn from(f: LuaFunction) -> Self {
210 LuaValue::Function(Rc::new(RefCell::new(f)))
211 }
212}
213impl From<LuaUserData> for LuaValue {
214 fn from(u: LuaUserData) -> Self {
215 LuaValue::UserData(Rc::new(RefCell::new(u)))
216 }
217}
218impl From<LuaThread> for LuaValue {
219 fn from(t: LuaThread) -> Self {
220 LuaValue::Thread(Rc::new(RefCell::new(t)))
221 }
222}
223
224#[derive(Debug, Clone)]
225pub struct LuaUserData {}