Skip to main content

luaur_vm/functions/
enumtable.rs

1use crate::functions::enumedge::enumedge;
2use crate::functions::enumedges::enumedges;
3use crate::functions::enumnode::enumnode;
4use crate::macros::dummynode::dummynode;
5use crate::macros::gcvalue::gcvalue;
6use crate::macros::getstr::getstr;
7use crate::macros::gfasttm::gfasttm;
8use crate::macros::hvalue::hvalue;
9use crate::macros::iscollectable::iscollectable;
10use crate::macros::nvalue::nvalue;
11use crate::macros::obj_2_gco::obj2gco;
12use crate::macros::registry::registry;
13use crate::macros::sizenode::sizenode;
14use crate::macros::svalue::svalue;
15use crate::macros::ttisnil::ttisnil;
16use crate::macros::ttisnumber::ttisnumber;
17use crate::macros::ttisstring::ttisstring;
18use crate::records::enum_context::EnumContext;
19use crate::records::gc_object::GCObject;
20use crate::records::lua_node::LuaNode;
21use crate::records::lua_t_value::TValue;
22use crate::records::lua_table::LuaTable;
23use crate::type_aliases::lua_table::LuaTable as LuaTableAlias;
24use crate::type_aliases::t_value::TValue as TValueAlias;
25use crate::type_aliases::tms::TMS;
26use core::ffi::{c_char, c_int};
27use core::ptr;
28
29#[allow(non_snake_case)]
30pub(crate) unsafe fn enumtable(ctx: *mut EnumContext, h: *mut LuaTable) {
31    let size = core::mem::size_of::<LuaTable>()
32        + if (*h).node == dummynode as *mut LuaNode {
33            0
34        } else {
35            sizenode!(h) as usize * core::mem::size_of::<LuaNode>()
36        }
37        + (*h).sizearray as usize * core::mem::size_of::<TValue>();
38
39    let obj = obj2gco!(h);
40
41    let h_ref = &*h;
42    let registry_ptr = registry!((*ctx).L);
43    let is_registry =
44        h == hvalue!(core::ptr::addr_of!(*registry_ptr) as *mut TValue) as *mut LuaTable;
45
46    enumnode(
47        ctx,
48        obj,
49        size,
50        if is_registry {
51            b"registry\0".as_ptr() as *const c_char
52        } else {
53            ptr::null()
54        },
55    );
56
57    if (*h).node != dummynode as *mut LuaNode {
58        let mut weakkey = false;
59        let mut weakvalue = false;
60
61        let g = (*(*ctx).L).global;
62        let metatable = (*h).metatable;
63        if !metatable.is_null() {
64            let mode = gfasttm(g, metatable, TMS::TM_MODE as i32);
65            if !mode.is_null() && ttisstring!(mode) {
66                let mode_str = svalue!(mode);
67                let mode_slice = core::ffi::CStr::from_ptr(mode_str).to_bytes();
68                weakkey = mode_slice.contains(&b'k');
69                weakvalue = mode_slice.contains(&b'v');
70            }
71        }
72
73        let node_count = sizenode!(h) as i32;
74        for i in 0..node_count {
75            let n = &(*(*h).node.add(i as usize));
76
77            if !ttisnil!(&n.val) && (iscollectable!(&n.key) || iscollectable!(&n.val)) {
78                if !weakkey && iscollectable!(&n.key) {
79                    enumedge(
80                        ctx,
81                        obj,
82                        gcvalue!(&n.key),
83                        b"[key]\0".as_ptr() as *const c_char,
84                    );
85                }
86
87                if !weakvalue && iscollectable!(&n.val) {
88                    if ttisstring!(&n.key) {
89                        enumedge(ctx, obj, gcvalue!(&n.val), svalue!(&n.key));
90                    } else if ttisnumber!(&n.key) {
91                        let mut buf = [0i8; 32];
92                        let nvalue_ptr = nvalue!(&n.key);
93                        extern "C" {
94                            fn snprintf(
95                                s: *mut c_char,
96                                n: usize,
97                                format: *const c_char,
98                                ...
99                            ) -> c_int;
100                        }
101                        snprintf(
102                            buf.as_mut_ptr(),
103                            buf.len(),
104                            b"%.14g\0".as_ptr() as *const c_char,
105                            nvalue_ptr,
106                        );
107                        enumedge(ctx, obj, gcvalue!(&n.val), buf.as_ptr());
108                    } else {
109                        let mut buf = [0i8; 32];
110                        let tt = n.key.tt();
111                        let global = (*(*ctx).L).global;
112                        let ttname_ptr = (*global).ttname.as_ptr().add(tt as usize);
113                        let name = getstr(ttname_ptr as *const crate::records::t_string::TString);
114                        extern "C" {
115                            fn snprintf(
116                                s: *mut c_char,
117                                n: usize,
118                                format: *const c_char,
119                                ...
120                            ) -> c_int;
121                        }
122                        snprintf(
123                            buf.as_mut_ptr(),
124                            buf.len(),
125                            b"[%s]\0".as_ptr() as *const c_char,
126                            name,
127                        );
128                        enumedge(ctx, obj, gcvalue!(&n.val), buf.as_ptr());
129                    }
130                }
131            }
132        }
133    }
134
135    if (*h).sizearray > 0 {
136        enumedges(
137            ctx,
138            obj,
139            (*h).array,
140            (*h).sizearray as usize,
141            b"array\0".as_ptr() as *const c_char,
142        );
143    }
144
145    if !(*h).metatable.is_null() {
146        enumedge(
147            ctx,
148            obj,
149            obj2gco!((*h).metatable),
150            b"metatable\0".as_ptr() as *const c_char,
151        );
152    }
153}