1use std::rc::Rc;
2
3use neige_infra::LuaType;
4
5use crate::{
6 state::LuaState,
7 value::{closure::RustFn, table::LuaTable, value::LuaValue},
8};
9
10use super::CallApi;
11
12pub trait AccessApi {
13 fn tp_name(&self, tp: LuaType) -> String;
14 fn ty_id(&self, idx: isize) -> LuaType;
15 fn is_none(&self, idx: isize) -> bool;
16 fn is_nil(&self, idx: isize) -> bool;
17 fn is_none_or_nil(&self, idx: isize) -> bool;
18 fn is_boolean(&self, idx: isize) -> bool;
19 fn is_integer(&self, idx: isize) -> bool;
20 fn is_number(&self, idx: isize) -> bool;
21 fn is_string(&self, idx: isize) -> bool;
22 fn is_rust_fn(&self, idx: isize) -> bool;
23 fn is_lua_tbl(&self, idx: isize) -> bool;
24 fn to_boolean(&self, idx: isize) -> bool;
25 fn to_integer(&self, idx: isize) -> i64;
26 fn to_integer_x(&self, idx: isize) -> Option<i64>;
27 fn to_number(&self, idx: isize) -> f64;
28 fn to_number_x(&self, idx: isize) -> Option<f64>;
29 fn to_string(&mut self, idx: isize) -> String;
30 fn to_string_x(&mut self, idx: isize) -> Option<String>;
31 fn to_rust_fn(&self, idx: isize) -> Option<RustFn>;
32 fn to_lua_tbl(&self, idx: isize) -> Option<Rc<LuaTable>>;
33 fn raw_len(&self, idx: isize) -> usize;
34}
35
36impl AccessApi for LuaState {
37 fn tp_name(&self, tp: LuaType) -> String {
39 let name = match tp {
40 LuaType::None => "no value",
41 LuaType::Nil => "nil",
42 LuaType::Boolean => "boolean",
43 LuaType::LightUserData => "light user data",
44 LuaType::Number => "number",
45 LuaType::String => "string",
46 LuaType::Table => "table",
47 LuaType::Function => "function",
48 LuaType::UserData => "user data",
49 LuaType::Thread => "thread",
50 LuaType::Integer => "integer",
51 };
52 name.into()
53 }
54
55 fn ty_id(&self, idx: isize) -> neige_infra::LuaType {
56 if self.stack_is_valid(idx) {
57 self.stack_get(idx).type_of()
58 } else {
59 LuaType::None
60 }
61 }
62
63 fn is_none(&self, idx: isize) -> bool {
64 self.ty_id(idx) == LuaType::None
65 }
66
67 fn is_nil(&self, idx: isize) -> bool {
68 self.ty_id(idx) == LuaType::Nil
69 }
70
71 fn is_none_or_nil(&self, idx: isize) -> bool {
72 self.is_nil(idx) || self.is_none(idx)
73 }
74
75 fn is_boolean(&self, idx: isize) -> bool {
76 self.ty_id(idx) == LuaType::Boolean
77 }
78
79 fn is_integer(&self, idx: isize) -> bool {
80 self.ty_id(idx) == LuaType::Integer
81 }
82
83 fn is_number(&self, idx: isize) -> bool {
84 self.ty_id(idx) == LuaType::Number
85 }
86
87 fn is_string(&self, idx: isize) -> bool {
88 let t = self.ty_id(idx);
89 t == LuaType::String || t == LuaType::Number
90 }
91
92 fn is_rust_fn(&self, idx: isize) -> bool {
93 let val = self.stack_get(idx);
94 if let LuaValue::Function(f) = val {
95 if let Some(_) = f.rust_fn {
96 return true;
97 }
98 }
99 return false;
100 }
101
102 fn is_lua_tbl(&self, idx: isize) -> bool {
103 self.ty_id(idx) == LuaType::Table
104 }
105
106 fn to_boolean(&self, idx: isize) -> bool {
107 self.stack_get(idx).convert_to_boolean()
108 }
109
110 fn to_integer(&self, idx: isize) -> i64 {
111 self.to_integer_x(idx).unwrap_or(0)
112 }
113
114 fn to_integer_x(&self, idx: isize) -> Option<i64> {
115 self.stack_get(idx).convert_to_integer()
116 }
117
118 fn to_number(&self, idx: isize) -> f64 {
119 self.to_number_x(idx).unwrap_or(0.0)
120 }
121
122 fn to_number_x(&self, idx: isize) -> Option<f64> {
123 self.stack_get(idx).convert_to_float()
124 }
125
126 fn to_string(&mut self, idx: isize) -> String {
127 self.to_string_x(idx).unwrap_or(format!(""))
128 }
129
130 fn to_string_x(&mut self, idx: isize) -> Option<String> {
131 let val = self.stack_get(idx);
132 match val {
133 LuaValue::Integer(i) => {
134 let s = format!("{}", i);
135 self.stack_set(idx, LuaValue::Str(s.clone()));
136 Some(s)
137 }
138 LuaValue::Number(f) => {
139 let s = format!("{}", f);
140 self.stack_set(idx, LuaValue::Str(s.clone()));
141 Some(s)
142 }
143 LuaValue::Str(s) => Some(s),
144 LuaValue::Table(_) => {
145 if let LuaValue::Function(c) = self.inline_get_meta_field(&val, "__tostring") {
146 self.stack_push(LuaValue::Function(c));
147 self.stack_push(val);
148 self.call(1, 1);
149 if let LuaValue::Str(s) = self.stack_get(-1) {
150 return Some(s);
151 }
152 }
153 None
154 }
155 _ => None,
156 }
157 }
158
159 fn to_rust_fn(&self, idx: isize) -> Option<RustFn> {
160 let val = self.stack_get(idx);
161 if let LuaValue::Function(f) = val {
162 if let Some(f) = &f.rust_fn {
163 return Some(*f);
164 }
165 }
166 None
167 }
168
169 fn to_lua_tbl(&self, idx: isize) -> Option<Rc<LuaTable>> {
170 let val = self.stack_get(idx);
171 if let LuaValue::Table(tbl) = val {
172 Some(tbl)
173 } else {
174 None
175 }
176 }
177
178 fn raw_len(&self, idx: isize) -> usize {
179 let val = self.stack_get(idx);
180 match val {
181 LuaValue::Str(s) => s.len(),
182 LuaValue::Table(t) => t.as_ref().arr.borrow().len(),
183 _ => 0,
184 }
185 }
186}