lua-shared 0.1.0

Really simple wrapper around lua_shared(_srv) that tries not to be a total burden when interfacing with gmod's lua.
Documentation
use std::{ffi::c_void, hint::unreachable_unchecked};

use crate::{lua_State, lua_loadx, pop, tolstring, LError, Status};

pub unsafe fn loadx<READER>(
    state: lua_State,
    reader: &mut READER,
    chunk_name: *const u8,
    mode: *const u8,
) -> std::result::Result<(), LError>
where
    READER: std::io::Read,
{
    struct ReaderState<'a, READER>
    where
        READER: std::io::Read,
    {
        buffer: [u8; 4096],
        reader: &'a mut READER,
    }
    unsafe extern "C" fn reader_callback<READER>(
        _: lua_State,
        userdata: *mut c_void,
        size: &mut usize,
    ) -> *const u8
    where
        READER: std::io::Read,
    {
        let reader = &mut *userdata.cast::<ReaderState<READER>>();
        *size = reader.reader.read(&mut reader.buffer).unwrap_or(0);
        reader.buffer.as_ptr()
    }
    let mut reader_state = Box::new(ReaderState {
        buffer: [0; 4096],
        reader: reader,
    });
    match lua_loadx(
        state,
        reader_callback::<READER>,
        reader_state.as_mut() as *mut ReaderState<READER> as _,
        chunk_name,
        mode,
    ) {
        Status::Ok => Ok(()),
        Status::SyntaxError => {
            let mut len = 0;
            let err = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
                tolstring(state, -1, &mut len),
                len,
            ))
            .to_string();
            pop!(state, 1);
            Err(LError::SyntaxError(err))
        }
        Status::MemoryError => {
            let mut len = 0;
            let err = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
                tolstring(state, -1, &mut len),
                len,
            ))
            .to_string();
            pop!(state, 1);
            Err(LError::MemoryError(err))
        }
        _ => unreachable_unchecked(),
    }
}