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)) => GcRef::ptr_eq(a, b) || a.as_bytes() == b.as_bytes(),
93 (LuaValue::Table(a), LuaValue::Table(b)) => GcRef::ptr_eq(a, b),
94 (LuaValue::Function(a), LuaValue::Function(b)) => closure_eq(a, b),
95 (LuaValue::UserData(a), LuaValue::UserData(b)) => GcRef::ptr_eq(a, b),
96 (LuaValue::LightUserData(a), LuaValue::LightUserData(b)) => a == b,
97 (LuaValue::Thread(a), LuaValue::Thread(b)) => GcRef::ptr_eq(a, b),
98 _ => false,
99 }
100 }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum F2Imod {
106 Floor,
107 Ceil,
108 Round,
109}
110
111fn closure_eq(a: &LuaClosure, b: &LuaClosure) -> bool {
115 match (a, b) {
116 (LuaClosure::Lua(x), LuaClosure::Lua(y)) => GcRef::ptr_eq(x, y),
117 (LuaClosure::C(x), LuaClosure::C(y)) => GcRef::ptr_eq(x, y),
118 (LuaClosure::LightC(x), LuaClosure::LightC(y)) => x == y,
119 _ => false,
120 }
121}
122
123#[derive(Debug)]
135pub struct LuaThread {
136 pub id: u64,
137}
138impl LuaThread {
139 pub fn new(id: u64) -> Self { LuaThread { id } }
140 pub fn placeholder() -> Self { LuaThread { id: 0 } }
141}
142
143