luadec/
ffi.rs

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
11/// Safe wrapper around the C decompilation function
12pub 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    // Ensure we always free the result, even if we return early
33    let _guard = ResultGuard(result_ptr);
34    
35    // Check for errors first
36    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    // Get the result
44    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
55/// RAII guard to ensure C memory is freed
56struct 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}