1use luadec_sys::{
2 luadec_result_t, luadec_decompile_buffer, luadec_free_result,
3 luadec_get_result, luadec_get_error
4};
5use std::ffi::CStr;
6use std::sync::Mutex;
7use crate::error::{DecompileError, Result};
8
9static DECOMPILE_MUTEX: Mutex<()> = Mutex::new(());
10
11pub fn decompile_bytecode_raw(bytecode: &[u8]) -> Result<String> {
13 if bytecode.is_empty() {
14 return Err(DecompileError::InvalidBytecode("Empty bytecode".to_string()));
15 }
16
17 let _lock = DECOMPILE_MUTEX.lock().map_err(|_| {
18 DecompileError::InternalError("Failed to acquire decompilation lock".to_string())
19 })?;
20
21 let result_ptr = unsafe {
22 luadec_decompile_buffer(
23 bytecode.as_ptr() as *const i8,
24 bytecode.len(),
25 )
26 };
27
28 if result_ptr.is_null() {
29 return Err(DecompileError::InternalError("Failed to get result".to_string()));
30 }
31
32 let _guard = ResultGuard(result_ptr);
34
35 let error_ptr = unsafe { luadec_get_error(result_ptr) };
37 if !error_ptr.is_null() {
38 let error_cstr = unsafe { CStr::from_ptr(error_ptr) };
39 let error_msg = error_cstr.to_string_lossy().to_string();
40 return Err(DecompileError::DecompilationFailed(error_msg));
41 }
42
43 let result_cstr_ptr = unsafe { luadec_get_result(result_ptr) };
45 if result_cstr_ptr.is_null() {
46 return Err(DecompileError::InternalError("No result returned".to_string()));
47 }
48
49 let result_cstr = unsafe { CStr::from_ptr(result_cstr_ptr) };
50 let result_string = result_cstr.to_string_lossy().to_string();
51
52 Ok(result_string)
53}
54
55struct ResultGuard(*mut luadec_result_t);
57
58impl Drop for ResultGuard {
59 fn drop(&mut self) {
60 unsafe {
61 luadec_free_result(self.0);
62 }
63 }
64}