luaur_analysis/functions/
parse_format_string.rs1use crate::records::builtin_types::BuiltinTypes;
2use crate::type_aliases::type_id::TypeId;
3use alloc::vec::Vec;
4use core::ffi::c_char;
5use core::ptr::NonNull;
6use core::slice;
7
8pub fn parse_format_string(
9 builtin_types: NonNull<BuiltinTypes>,
10 data: *const c_char,
11 size: usize,
12) -> Vec<TypeId> {
13 let options = b"cdiouxXeEfgGqs*";
14 let data_slice = unsafe { slice::from_raw_parts(data as *const u8, size) };
15 let mut result = Vec::new();
16 let builtin_types = unsafe { builtin_types.as_ref() };
17
18 let mut i = 0;
19 while i < size {
20 if data_slice[i] == b'%' {
21 i += 1;
22
23 if i < size && data_slice[i] == b'%' {
24 i += 1;
25 continue;
26 }
27
28 while i < size
29 && !(data_slice[i] > 0
30 && (data_slice[i].is_ascii_alphabetic() || data_slice[i] == b'*'))
31 {
32 i += 1;
33 }
34
35 if i == size {
36 break;
37 }
38
39 let c = data_slice[i];
40 if c == b'q' || c == b's' {
41 result.push(builtin_types.stringType);
42 } else if c == b'*' {
43 result.push(builtin_types.unknownType);
44 } else if options.contains(&c) {
45 result.push(builtin_types.numberType);
46 } else {
47 result.push(builtin_types.error_recovery_type(builtin_types.anyType));
48 }
49 }
50 i += 1;
51 }
52
53 result
54}