Skip to main content

luaur_analysis/functions/
parse_pattern_string.rs

1use 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;
6
7pub fn parse_pattern_string(
8    builtin_types: NonNull<BuiltinTypes>,
9    data: *const c_char,
10    size: usize,
11) -> Vec<TypeId> {
12    let builtin_types = unsafe { builtin_types.as_ref() };
13    let data = unsafe { core::slice::from_raw_parts(data as *const u8, size) };
14
15    let mut result = Vec::new();
16    let mut depth = 0;
17    let mut parsing_set = false;
18
19    let mut i = 0;
20    while i < size {
21        let b = data[i];
22        if b == b'%' {
23            i += 1;
24            if !parsing_set && i < size && data[i] == b'b' {
25                i += 2;
26            }
27        } else if !parsing_set && b == b'[' {
28            parsing_set = true;
29            if i + 1 < size && data[i + 1] == b']' {
30                i += 1;
31            }
32        } else if parsing_set && b == b']' {
33            parsing_set = false;
34        } else if b == b'(' {
35            if !parsing_set {
36                if i + 1 < size && data[i + 1] == b')' {
37                    i += 1;
38                    result.push(builtin_types.optionalNumberType);
39                } else {
40                    depth += 1;
41                    result.push(builtin_types.optionalStringType);
42                }
43            }
44        } else if b == b')' {
45            if !parsing_set {
46                depth -= 1;
47                if depth < 0 {
48                    break;
49                }
50            }
51        }
52        i += 1;
53    }
54
55    if depth != 0 || parsing_set {
56        return Vec::new();
57    }
58
59    if result.is_empty() {
60        result.push(builtin_types.optionalStringType);
61    }
62
63    result
64}