luaur_web/functions/
run_code.rs1use alloc::string::String;
9use alloc::string::ToString;
10use core::ffi::{c_char, c_void};
11
12use luaur_compiler::functions::luau_compile::luau_compile;
13use luaur_vm::enums::lua_status::lua_Status;
14use luaur_vm::functions::lua_debugtrace::lua_debugtrace;
15use luaur_vm::functions::lua_getinfo::lua_getinfo;
16use luaur_vm::functions::lua_gettop::lua_gettop;
17use luaur_vm::functions::lua_insert::lua_insert;
18use luaur_vm::functions::lua_l_checkstack::lua_l_checkstack;
19use luaur_vm::functions::lua_newthread::lua_newthread;
20use luaur_vm::functions::lua_pcall::lua_pcall;
21use luaur_vm::functions::lua_pushvalue::lua_pushvalue;
22use luaur_vm::functions::lua_remove::lua_remove;
23use luaur_vm::functions::lua_resume::lua_resume;
24use luaur_vm::functions::lua_tolstring::lua_tolstring;
25use luaur_vm::functions::lua_xmove::lua_xmove;
26use luaur_vm::functions::luau_load::luau_load;
27use luaur_vm::macros::lua_minstack::LUA_MINSTACK;
28use luaur_vm::macros::lua_pop::lua_pop;
29use luaur_vm::records::lua_debug::LuaDebug;
30use luaur_vm::type_aliases::lua_state::lua_State;
31
32extern "C" {
33 fn free(ptr: *mut c_void);
34}
35
36pub fn run_code(l: *mut lua_State, source: &str) -> String {
37 unsafe {
38 let mut bytecode_size: usize = 0;
41 let bytecode = luau_compile(
42 source.as_ptr() as *const c_char,
43 source.len(),
44 core::ptr::null_mut(),
45 &mut bytecode_size,
46 );
47
48 let result = luau_load(l, c"=stdin".as_ptr(), bytecode, bytecode_size, 0);
50
51 free(bytecode as *mut c_void);
53
54 if result != 0 {
55 let mut len: usize = 0;
57 let msg = lua_tolstring(l, -1, &mut len);
58
59 let error =
60 core::str::from_utf8_unchecked(core::slice::from_raw_parts(msg as *const u8, len))
61 .to_string();
62 lua_pop(l, 1);
63
64 return error;
65 }
66
67 let t = lua_newthread(l);
69
70 lua_pushvalue(l, -2);
74 lua_remove(l, -3);
75 lua_xmove(l, t, 1);
76
77 let status = lua_resume(t, core::ptr::null_mut(), 0);
79
80 if status == 0 {
81 let n = lua_gettop(t);
82
83 if n != 0 {
84 lua_l_checkstack(t, LUA_MINSTACK, "too many results to print");
85 luaur_vm::macros::lua_getglobal::lua_getglobal(t, c"print".as_ptr());
86 lua_insert(t, 1);
87 lua_pcall(t, n, 0, 0);
88 }
89
90 lua_pop(l, 1); String::new()
92 } else {
93 let mut error = String::new();
94
95 let mut ar = LuaDebug {
98 name: core::ptr::null(),
99 what: core::ptr::null(),
100 source: core::ptr::null(),
101 short_src: core::ptr::null(),
102 linedefined: 0,
103 currentline: 0,
104 nupvals: 0,
105 nparams: 0,
106 isvararg: 0,
107 userdata: core::ptr::null_mut(),
108 ssbuf: [0; 256],
109 };
110 if lua_getinfo(l, 0, c"sln".as_ptr(), &mut ar) != 0 {
111 if !ar.short_src.is_null() {
112 error.push_str(&core::ffi::CStr::from_ptr(ar.short_src).to_string_lossy());
113 }
114 error.push(':');
115 error.push_str(&ar.currentline.to_string());
116 error.push_str(": ");
117 }
118
119 if status == lua_Status::LUA_YIELD as i32 {
120 error.push_str("thread yielded unexpectedly");
121 } else {
122 let str_ptr = lua_tolstring(t, -1, core::ptr::null_mut());
124 if !str_ptr.is_null() {
125 error.push_str(&core::ffi::CStr::from_ptr(str_ptr).to_string_lossy());
126 }
127 }
128
129 error.push_str("\nstack backtrace:\n");
130 let trace = lua_debugtrace(t);
131 if !trace.is_null() {
132 error.push_str(&core::ffi::CStr::from_ptr(trace).to_string_lossy());
133 }
134
135 lua_pop(l, 1); error
137 }
138 }
139}