luadec/lib.rs
1//! # LuaDec - Lua 5.1 Bytecode Decompiler
2//!
3//! This crate provides Rust bindings for the LuaDec library, which decompiles
4//! Lua 5.1 bytecode back into readable Lua source code.
5//!
6//! ## Example
7//!
8//! ```rust,no_run
9//! use luadec::{decompile, DecompileError};
10//! use std::fs;
11//!
12//! fn main() -> Result<(), DecompileError> {
13//! // Read compiled Lua bytecode
14//! let bytecode = fs::read("example.luac")?;
15//!
16//! // Decompile to Lua source code
17//! let source = decompile(&bytecode)?;
18//!
19//! println!("Decompiled source:\n{}", source);
20//! Ok(())
21//! }
22//! ```
23
24pub mod error;
25pub mod ffi;
26
27pub use error::{DecompileError, Result};
28
29use std::fs;
30use std::path::Path;
31
32/// Decompile Lua 5.1 bytecode from a byte slice
33///
34/// # Arguments
35///
36/// * `bytecode` - The compiled Lua bytecode as a byte slice
37///
38/// # Returns
39///
40/// Returns the decompiled Lua source code as a String, or a DecompileError if
41/// decompilation fails.
42///
43/// # Example
44///
45/// ```rust,no_run
46/// use luadec::decompile;
47/// use std::fs;
48///
49/// let bytecode = fs::read("hello.luac")?;
50/// let source = decompile(&bytecode)?;
51/// println!("{}", source);
52/// # Ok::<(), luadec::DecompileError>(())
53/// ```
54pub fn decompile(bytecode: &[u8]) -> Result<String> {
55 ffi::decompile_bytecode_raw(bytecode)
56}
57
58/// Decompile Lua 5.1 bytecode from a file
59///
60/// # Arguments
61///
62/// * `path` - Path to the compiled Lua bytecode file (.luac)
63///
64/// # Returns
65///
66/// Returns the decompiled Lua source code as a String, or a DecompileError if
67/// reading the file or decompilation fails.
68///
69/// # Example
70///
71/// ```rust,no_run
72/// use luadec::decompile_file;
73///
74/// let source = decompile_file("hello.luac")?;
75/// println!("{}", source);
76/// # Ok::<(), luadec::DecompileError>(())
77/// ```
78pub fn decompile_file<P: AsRef<Path>>(path: P) -> Result<String> {
79 let bytecode = fs::read(path)?;
80 decompile(&bytecode)
81}
82
83/// A high-level decompiler interface for more advanced usage
84pub struct Decompiler {
85 // Future: could add configuration options here
86 // For now, we use the default behavior
87}
88
89impl Decompiler {
90 /// Create a new decompiler instance
91 pub fn new() -> Self {
92 Self {}
93 }
94
95 /// Decompile bytecode with this decompiler instance
96 pub fn decompile(&self, bytecode: &[u8]) -> Result<String> {
97 decompile(bytecode)
98 }
99
100 /// Decompile a file with this decompiler instance
101 pub fn decompile_file<P: AsRef<Path>>(&self, path: P) -> Result<String> {
102 decompile_file(path)
103 }
104}
105
106impl Default for Decompiler {
107 fn default() -> Self {
108 Self::new()
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn test_empty_bytecode() {
118 let result = decompile(&[]);
119 assert!(result.is_err());
120 match result.unwrap_err() {
121 DecompileError::InvalidBytecode(_) => {},
122 other => panic!("Expected InvalidBytecode error, got: {:?}", other),
123 }
124 }
125
126 #[test]
127 fn test_invalid_bytecode() {
128 let invalid_bytecode = b"not lua bytecode";
129 let result = decompile(invalid_bytecode);
130 assert!(result.is_err());
131 }
132
133 #[test]
134 fn test_decompiler_struct() {
135 let decompiler = Decompiler::new();
136 let result = decompiler.decompile(&[]);
137 assert!(result.is_err());
138 }
139
140 #[test]
141 fn test_concurrent_decompile() {
142 use std::thread;
143 use std::sync::Arc;
144
145 let invalid_bytecode = Arc::new(vec![1, 2, 3, 4, 5]);
146 let mut handles = vec![];
147
148 // Spawn multiple threads that try to decompile simultaneously
149 for _ in 0..10 {
150 let bytecode = invalid_bytecode.clone();
151 let handle = thread::spawn(move || {
152 let result = decompile(&bytecode);
153 // All should fail with invalid bytecode, but shouldn't crash
154 assert!(result.is_err());
155 });
156 handles.push(handle);
157 }
158
159 // Wait for all threads to complete
160 for handle in handles {
161 handle.join().expect("Thread panicked");
162 }
163 }
164
165}