luaur_cli_lib/functions/read_file.rs
1use alloc::string::String;
2
3pub fn read_file(name: &str) -> Option<String> {
4 // Use the standard library's filesystem layer rather than hand-rolled C
5 // `fopen`/`_wfopen` FFI. `std::fs` handles cross-platform path encoding
6 // (including UTF-16 wide paths with correct NUL termination on Windows) and
7 // is free of the unsafe pointer plumbing the previous port carried. Files
8 // are read as raw bytes, mirroring the C++ reader's binary (`"rb"`) mode.
9 //
10 // Several callers hand us a C-string-style path that still carries its
11 // trailing NUL (e.g. `to_bytes_with_nul()` / `nul_terminated()`), relying on
12 // the old `fopen` stopping at the first NUL. `std::fs` treats an interior
13 // NUL as an error, so reproduce that termination behaviour here.
14 let name = match name.find('\0') {
15 Some(end) => &name[..end],
16 None => name,
17 };
18 let bytes = std::fs::read(name).ok()?;
19
20 // SAFETY: Luau source may contain arbitrary bytes inside string literals;
21 // the C++ reader stores them verbatim in a `std::string` and hands the raw
22 // buffer to the compiler. We mirror that — no UTF-8 validation/rewriting.
23 let mut result = unsafe { String::from_utf8_unchecked(bytes) };
24
25 // Skip first line if it's a shebang
26 if result.len() > 2 && result.as_bytes()[0] == b'#' && result.as_bytes()[1] == b'!' {
27 if let Some(newline_pos) = result.find('\n') {
28 result.drain(0..=newline_pos);
29 }
30 }
31
32 Some(result)
33}