1use neige_infra::LUA_RIDX_GLOBALS;
2
3use crate::{api::CallApi, state::LuaState, value::value::LuaValue};
4
5pub trait SetApi {
6 fn set_table(&mut self, idx: isize);
7 fn set_field(&mut self, idx: isize, key: &str);
8 fn set_i(&mut self, idx: isize, i: i64);
9 fn set_meta_table(&mut self, idx: isize);
10 fn raw_set(&mut self, idx: isize);
11 fn raw_set_i(&mut self, idx: isize, i: i64);
12 fn set_global(&mut self, name: &str);
13}
14
15impl SetApi for LuaState {
16 fn set_table(&mut self, idx: isize) {
17 let t = self.stack_get(idx);
18 let v = self.stack_pop();
19 let k = self.stack_pop();
20 self.inline_set_table(t, k, v, false)
21 }
22
23 fn set_field(&mut self, idx: isize, key: &str) {
24 let t = self.stack_get(idx);
25 let v = self.stack_pop();
26 self.inline_set_table(t, LuaValue::Str(key.into()), v, false)
27 }
28
29 fn set_i(&mut self, idx: isize, i: i64) {
30 let t = self.stack_get(idx);
31 let v = self.stack_pop();
32 self.inline_set_table(t, LuaValue::Integer(i), v, false)
33 }
34
35 fn set_meta_table(&mut self, idx: isize) {
36 let val = self.stack_get(idx);
37 let mt_tb = self.stack_pop();
38 match mt_tb {
39 LuaValue::Nil => self.inline_set_meta_table(&val, None),
40 LuaValue::Table(tb) => self.inline_set_meta_table(&val, Some(tb)),
41 _ => panic!("table expected!"),
42 }
43 }
44
45 fn raw_set(&mut self, idx: isize) {
46 let t = self.stack_get(idx);
47 let v = self.stack_pop();
48 let k = self.stack_pop();
49 self.inline_set_table(t, k, v, true)
50 }
51
52 fn raw_set_i(&mut self, idx: isize, i: i64) {
53 let t = self.stack_get(idx);
54 let v = self.stack_pop();
55 self.inline_set_table(t, LuaValue::Integer(i), v, true);
56 }
57
58 fn set_global(&mut self, name: &str) {
59 let t = self.registry_get(&LuaValue::Integer(LUA_RIDX_GLOBALS));
60 let v = self.stack_pop();
61 self.inline_set_table(t, LuaValue::Str(name.into()), v, false)
62 }
63}
64
65impl LuaState {
66 fn inline_set_table(&mut self, t: LuaValue, k: LuaValue, v: LuaValue, raw: bool) {
67 if let LuaValue::Table(tbl) = &t {
68 if raw || !tbl.get(&k).is_nil() || !tbl.has_meta_field("__newindex") {
69 tbl.put(k, v);
70 return;
71 }
72 }
73 if !raw {
74 let mf = self.inline_get_meta_field(&t, "__newindex");
75 match &mf {
76 LuaValue::Table(_) => {
77 self.inline_set_table(mf, k, v, false);
78 return;
79 }
80 LuaValue::Function(_) => {
81 self.stack_push(mf);
82 self.stack_push(t);
83 self.stack_push(k);
84 self.stack_push(v);
85 self.call(3, 0);
86 return;
87 }
88 _ => {}
89 }
90 }
91 panic!("not a table!")
92 }
93}