lu 0.5.1

A library for embedding Luau
Documentation
use std::ffi::c_char;
use std::ptr::null;

#[derive(Default, Clone, Copy)]
pub enum OptimizationLevel {
    None,
    Some,
    #[default]
    Full,
}

impl From<OptimizationLevel> for i32 {
    fn from(level: OptimizationLevel) -> Self {
        match level {
            OptimizationLevel::None => 0,
            OptimizationLevel::Some => 1,
            OptimizationLevel::Full => 2,
        }
    }
}

#[derive(Default, Clone, Copy)]
pub enum DebugInfoLevel {
    None,
    #[default]
    Some,
    Full,
}

impl From<DebugInfoLevel> for i32 {
    fn from(level: DebugInfoLevel) -> Self {
        match level {
            DebugInfoLevel::None => 0,
            DebugInfoLevel::Some => 1,
            DebugInfoLevel::Full => 2,
        }
    }
}

#[derive(Default)]
pub struct Compiler {
    optimization_level: OptimizationLevel,
    debug_level: DebugInfoLevel,
}

impl Compiler {
    pub fn with_optimization_level(mut self, level: OptimizationLevel) -> Self {
        self.optimization_level = level;
        self
    }

    pub fn with_debug_level(mut self, level: DebugInfoLevel) -> Self {
        self.debug_level = level;
        self
    }

    pub fn compile(&self, source: &[u8]) -> CompileResult {
        let mut options = sys::lua_CompileOptions {
            optimizationLevel: self.optimization_level.into(),
            debugLevel: self.debug_level.into(),
            typeInfoLevel: 0,
            coverageLevel: 0,
            vectorLib: null(),
            vectorCtor: null(),
            vectorType: null(),
            mutableGlobals: null(),
            userdataTypes: null(),
            librariesWithKnownMembers: null(),
            libraryMemberTypeCb: None,
            libraryMemberConstantCb: None,
            disabledBuiltins: null(),
        };

        let mut len = 0;
        let ptr = unsafe {
            sys::luau_compile(source.as_ptr().cast(), source.len(), &mut options, &mut len)
        };

        CompileResult { ptr, len }
    }
}

pub struct CompileResult {
    ptr: *mut c_char,
    len: usize,
}

impl Drop for CompileResult {
    fn drop(&mut self) {
        unsafe { libc::free(self.ptr.cast()) }
    }
}

impl CompileResult {
    pub fn bytecode(&self) -> Bytecode {
        Bytecode(unsafe { std::slice::from_raw_parts(self.ptr.cast(), self.len) })
    }
}

pub struct Bytecode<'a>(&'a [u8]);

impl Bytecode<'_> {
    pub fn ptr(&self) -> *const c_char {
        self.0.as_ptr().cast()
    }

    #[allow(clippy::len_without_is_empty)]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    pub fn result(&self) -> Result<(), &str> {
        if self.0.first().copied().unwrap() == 0 {
            Err(unsafe { std::str::from_utf8_unchecked(&self.0[1..]) })
        } else {
            Ok(())
        }
    }
}