1use crate::closure::LuaClosure;
4use crate::gc::GcRef;
5use crate::string::LuaString;
6use crate::userdata::LuaUserData;
7use std::ffi::c_void;
8
9pub use crate::table::LuaTable;
10
11#[derive(Debug, Clone, Copy)]
13pub enum LuaValue {
14 Nil,
15 Bool(bool),
16 Int(i64),
17 Float(f64),
18 Str(GcRef<LuaString>),
19 Table(GcRef<LuaTable>),
20 Function(LuaClosure),
21 UserData(GcRef<LuaUserData>),
22 LightUserData(*mut c_void),
23 Thread(GcRef<LuaThread>),
24}
25
26impl LuaValue {
27 pub fn type_tag(&self) -> crate::LuaType {
28 use crate::LuaType::*;
29 match self {
30 LuaValue::Nil => Nil,
31 LuaValue::Bool(_) => Boolean,
32 LuaValue::Int(_) => Number,
33 LuaValue::Float(_) => Number,
34 LuaValue::Str(_) => String,
35 LuaValue::Table(_) => Table,
36 LuaValue::Function(_) => Function,
37 LuaValue::UserData(_) => UserData,
38 LuaValue::LightUserData(_) => LightUserData,
39 LuaValue::Thread(_) => Thread,
40 }
41 }
42
43 pub fn type_name(&self) -> &'static str {
44 match self {
45 LuaValue::Nil => "nil",
46 LuaValue::Bool(_) => "boolean",
47 LuaValue::Int(_) => "number",
48 LuaValue::Float(_) => "number",
49 LuaValue::Str(_) => "string",
50 LuaValue::Table(_) => "table",
51 LuaValue::Function(_) => "function",
52 LuaValue::UserData(_) => "userdata",
53 LuaValue::LightUserData(_) => "userdata",
54 LuaValue::Thread(_) => "thread",
55 }
56 }
57
58 pub fn is_nil(&self) -> bool { matches!(self, LuaValue::Nil) }
59 pub fn is_falsy(&self) -> bool { matches!(self, LuaValue::Nil | LuaValue::Bool(false)) }
60 pub fn is_truthy(&self) -> bool { !self.is_falsy() }
61 pub fn is_collectable(&self) -> bool {
62 matches!(self,
63 LuaValue::Str(_) | LuaValue::Table(_) | LuaValue::Function(_) |
64 LuaValue::UserData(_) | LuaValue::Thread(_))
65 }
66
67 pub fn as_int(&self) -> Option<i64> {
68 match self { LuaValue::Int(i) => Some(*i), _ => None }
69 }
70 pub fn as_float(&self) -> Option<f64> {
71 match self { LuaValue::Float(f) => Some(*f), _ => None }
72 }
73 pub fn as_string(&self) -> Option<&GcRef<LuaString>> {
74 match self { LuaValue::Str(s) => Some(s), _ => None }
75 }
76 pub fn as_table(&self) -> Option<&GcRef<LuaTable>> {
77 match self { LuaValue::Table(t) => Some(t), _ => None }
78 }
79}
80
81impl Default for LuaValue {
82 fn default() -> Self { LuaValue::Nil }
83}
84
85impl PartialEq for LuaValue {
86 fn eq(&self, other: &Self) -> bool {
87 match (self, other) {
88 (LuaValue::Nil, LuaValue::Nil) => true,
89 (LuaValue::Bool(a), LuaValue::Bool(b)) => a == b,
90 (LuaValue::Int(a), LuaValue::Int(b)) => a == b,
91 (LuaValue::Float(a), LuaValue::Float(b)) => a == b,
92 (LuaValue::Str(a), LuaValue::Str(b)) => {
93 GcRef::ptr_eq(a, b) || (a.hash() == b.hash() && a.as_bytes() == b.as_bytes())
94 }
95 (LuaValue::Table(a), LuaValue::Table(b)) => GcRef::ptr_eq(a, b),
96 (LuaValue::Function(a), LuaValue::Function(b)) => closure_eq(a, b),
97 (LuaValue::UserData(a), LuaValue::UserData(b)) => GcRef::ptr_eq(a, b),
98 (LuaValue::LightUserData(a), LuaValue::LightUserData(b)) => a == b,
99 (LuaValue::Thread(a), LuaValue::Thread(b)) => GcRef::ptr_eq(a, b),
100 _ => false,
101 }
102 }
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum F2Imod {
108 Floor,
109 Ceil,
110 Round,
111}
112
113fn closure_eq(a: &LuaClosure, b: &LuaClosure) -> bool {
117 match (a, b) {
118 (LuaClosure::Lua(x), LuaClosure::Lua(y)) => GcRef::ptr_eq(x, y),
119 (LuaClosure::C(x), LuaClosure::C(y)) => GcRef::ptr_eq(x, y),
120 (LuaClosure::LightC(x), LuaClosure::LightC(y)) => x == y,
121 _ => false,
122 }
123}
124
125#[derive(Debug)]
137pub struct LuaThread {
138 pub id: u64,
139}
140impl LuaThread {
141 pub fn new(id: u64) -> Self { LuaThread { id } }
142 pub fn placeholder() -> Self { LuaThread { id: 0 } }
143}
144
145