Skip to main content

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}