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}