lua_shared/
loadx.rs

1use std::{ffi::c_void, hint::unreachable_unchecked};
2
3use crate::{lua_State, lua_loadx, pop, tolstring, LError, Status};
4
5pub unsafe fn loadx<READER>(
6    state: lua_State,
7    reader: &mut READER,
8    chunk_name: *const u8,
9    mode: *const u8,
10) -> std::result::Result<(), LError>
11where
12    READER: std::io::Read,
13{
14    struct ReaderState<'a, READER>
15    where
16        READER: std::io::Read,
17    {
18        buffer: [u8; 4096],
19        reader: &'a mut READER,
20    }
21    unsafe extern "C" fn reader_callback<READER>(
22        _: lua_State,
23        userdata: *mut c_void,
24        size: &mut usize,
25    ) -> *const u8
26    where
27        READER: std::io::Read,
28    {
29        let reader = &mut *userdata.cast::<ReaderState<READER>>();
30        *size = reader.reader.read(&mut reader.buffer).unwrap_or(0);
31        reader.buffer.as_ptr()
32    }
33    let mut reader_state = Box::new(ReaderState {
34        buffer: [0; 4096],
35        reader: reader,
36    });
37    match lua_loadx(
38        state,
39        reader_callback::<READER>,
40        reader_state.as_mut() as *mut ReaderState<READER> as _,
41        chunk_name,
42        mode,
43    ) {
44        Status::Ok => Ok(()),
45        Status::SyntaxError => {
46            let mut len = 0;
47            let err = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
48                tolstring(state, -1, &mut len),
49                len,
50            ))
51            .to_string();
52            pop!(state, 1);
53            Err(LError::SyntaxError(err))
54        }
55        Status::MemoryError => {
56            let mut len = 0;
57            let err = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
58                tolstring(state, -1, &mut len),
59                len,
60            ))
61            .to_string();
62            pop!(state, 1);
63            Err(LError::MemoryError(err))
64        }
65        _ => unreachable_unchecked(),
66    }
67}