Skip to main content

luaur_cli_lib/functions/
to_utf_8.rs

1use alloc::string::String;
2use core::ffi::c_int;
3
4use luaur_common::macros::luau_assert::LUAU_ASSERT;
5
6#[allow(non_upper_case_globals)]
7const CP_UTF8: u32 = 65001;
8
9extern "system" {
10    fn WideCharToMultiByte(
11        code_page: u32,
12        dw_flags: u32,
13        lp_wide_char_str: *const u16,
14        cch_wide_char: c_int,
15        lp_multi_byte_str: *mut core::ffi::c_char,
16        cb_multi_byte: c_int,
17        lp_default_char: *const core::ffi::c_char,
18        lp_used_default_char: *mut i32,
19    ) -> c_int;
20}
21
22pub fn to_utf_8(path: &[u16]) -> String {
23    let path_ptr = path.as_ptr();
24    let path_len = path.len() as c_int;
25
26    let result = unsafe {
27        WideCharToMultiByte(
28            CP_UTF8,
29            0,
30            path_ptr,
31            path_len,
32            core::ptr::null_mut(),
33            0,
34            core::ptr::null(),
35            core::ptr::null_mut(),
36        )
37    };
38    LUAU_ASSERT!(result > 0);
39
40    let mut buf = vec![0u8; result as usize];
41    unsafe {
42        WideCharToMultiByte(
43            CP_UTF8,
44            0,
45            path_ptr,
46            path_len,
47            buf.as_mut_ptr() as *mut core::ffi::c_char,
48            result,
49            core::ptr::null(),
50            core::ptr::null_mut(),
51        );
52    }
53
54    // Safety: WideCharToMultiByte with CP_UTF8 always produces valid UTF-8.
55    unsafe { String::from_utf8_unchecked(buf) }
56}