blob: 1ed68458ae3a5cd1bcfc66a2f5713d991c5f5ab5 [file]
from enum import Enum
from typing import List
import re
class RustType(Enum):
Other = 0
Struct = 1
Tuple = 2
CStyleVariant = 3
TupleVariant = 4
StructVariant = 5
Enum = 6
Empty = 7
SingletonEnum = 8
RegularEnum = 9
CompressedEnum = 10
Union = 11
Indirection = 12
StdString = 13
StdOsString = 14
StdStr = 15
StdSlice = 16
StdVec = 17
StdVecDeque = 18
StdBTreeSet = 19
StdBTreeMap = 20
StdHashMap = 21
StdHashSet = 22
StdRc = 23
StdArc = 24
StdCell = 25
StdRef = 26
StdRefMut = 27
StdRefCell = 28
StdNonZeroNumber = 29
StdPath = 30
StdPathBuf = 31
STD_STRING_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)String$")
STD_STR_REGEX = re.compile(r"^&(mut )?str$")
STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.+\]$")
STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::([a-z_]+::)+)OsString$")
STD_VEC_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)Vec<.+>$")
STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)VecDeque<.+>$")
STD_BTREE_SET_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)BTreeSet<.+>$")
STD_BTREE_MAP_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)BTreeMap<.+>$")
STD_HASH_MAP_REGEX = re.compile(r"^(std::collections::([a-z_]+::)+)HashMap<.+>$")
STD_HASH_SET_REGEX = re.compile(r"^(std::collections::([a-z_]+::)+)HashSet<.+>$")
STD_RC_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)Rc<.+>$")
STD_ARC_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)Arc<.+>$")
STD_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)Cell<.+>$")
STD_REF_REGEX = re.compile(r"^(core::([a-z_]+::)+)Ref<.+>$")
STD_REF_MUT_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefMut<.+>$")
STD_REF_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefCell<.+>$")
STD_NONZERO_NUMBER_REGEX = re.compile(r"^(core::([a-z_]+::)+)NonZero<.+>$")
STD_PATHBUF_REGEX = re.compile(r"^(std::([a-z_]+::)+)PathBuf$")
STD_PATH_REGEX = re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$")
ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
ENUM_DISR_FIELD_NAME = "<<variant>>"
ENUM_LLDB_ENCODED_VARIANTS = "$variants$"
STD_TYPE_TO_REGEX = {
RustType.StdString: STD_STRING_REGEX,
RustType.StdOsString: STD_OS_STRING_REGEX,
RustType.StdStr: STD_STR_REGEX,
RustType.StdSlice: STD_SLICE_REGEX,
RustType.StdVec: STD_VEC_REGEX,
RustType.StdVecDeque: STD_VEC_DEQUE_REGEX,
RustType.StdHashMap: STD_HASH_MAP_REGEX,
RustType.StdHashSet: STD_HASH_SET_REGEX,
RustType.StdBTreeSet: STD_BTREE_SET_REGEX,
RustType.StdBTreeMap: STD_BTREE_MAP_REGEX,
RustType.StdRc: STD_RC_REGEX,
RustType.StdArc: STD_ARC_REGEX,
RustType.StdRef: STD_REF_REGEX,
RustType.StdRefMut: STD_REF_MUT_REGEX,
RustType.StdRefCell: STD_REF_CELL_REGEX,
RustType.StdCell: STD_CELL_REGEX,
RustType.StdNonZeroNumber: STD_NONZERO_NUMBER_REGEX,
RustType.StdPath: STD_PATH_REGEX,
RustType.StdPathBuf: STD_PATHBUF_REGEX,
}
def is_tuple_fields(fields: List) -> bool:
for f in fields:
name = str(f.name)
if not name.startswith("__") or not name[2:].isdigit():
return False
return True
def classify_struct(name: str, fields: List) -> RustType:
if len(fields) == 0:
return RustType.Empty
for ty, regex in STD_TYPE_TO_REGEX.items():
if regex.match(name):
return ty
# <<variant>> is emitted by GDB while LLDB(18.1+) emits "$variants$"
if (
fields[0].name == ENUM_DISR_FIELD_NAME
or fields[0].name == ENUM_LLDB_ENCODED_VARIANTS
):
return RustType.Enum
if is_tuple_fields(fields):
return RustType.Tuple
return RustType.Struct
def classify_union(fields: List) -> RustType:
if len(fields) == 0:
return RustType.Empty
first_variant_name = fields[0].name
if first_variant_name is None:
if len(fields) == 1:
return RustType.SingletonEnum
else:
return RustType.RegularEnum
elif first_variant_name.startswith(ENCODED_ENUM_PREFIX):
assert len(fields) == 1
return RustType.CompressedEnum
else:
return RustType.RegularEnum