neige_lua/api/
access.rs

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    /// 获取类型名
38    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}