1import re 2 3 4class RustType(object): 5 OTHER = "Other" 6 STRUCT = "Struct" 7 TUPLE = "Tuple" 8 CSTYLE_VARIANT = "CStyleVariant" 9 TUPLE_VARIANT = "TupleVariant" 10 STRUCT_VARIANT = "StructVariant" 11 ENUM = "Enum" 12 EMPTY = "Empty" 13 SINGLETON_ENUM = "SingletonEnum" 14 REGULAR_ENUM = "RegularEnum" 15 COMPRESSED_ENUM = "CompressedEnum" 16 REGULAR_UNION = "RegularUnion" 17 18 STD_STRING = "StdString" 19 STD_OS_STRING = "StdOsString" 20 STD_STR = "StdStr" 21 STD_SLICE = "StdSlice" 22 STD_VEC = "StdVec" 23 STD_VEC_DEQUE = "StdVecDeque" 24 STD_BTREE_SET = "StdBTreeSet" 25 STD_BTREE_MAP = "StdBTreeMap" 26 STD_HASH_MAP = "StdHashMap" 27 STD_HASH_SET = "StdHashSet" 28 STD_RC = "StdRc" 29 STD_ARC = "StdArc" 30 STD_CELL = "StdCell" 31 STD_REF = "StdRef" 32 STD_REF_MUT = "StdRefMut" 33 STD_REF_CELL = "StdRefCell" 34 STD_NONZERO_NUMBER = "StdNonZeroNumber" 35 36 37STD_STRING_REGEX = re.compile(r"^(alloc::(\w+::)+)String$") 38STD_STR_REGEX = re.compile(r"^&(mut )?str$") 39STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.+\]$") 40STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::(\w+::)+)OsString$") 41STD_VEC_REGEX = re.compile(r"^(alloc::(\w+::)+)Vec<.+>$") 42STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::(\w+::)+)VecDeque<.+>$") 43STD_BTREE_SET_REGEX = re.compile(r"^(alloc::(\w+::)+)BTreeSet<.+>$") 44STD_BTREE_MAP_REGEX = re.compile(r"^(alloc::(\w+::)+)BTreeMap<.+>$") 45STD_HASH_MAP_REGEX = re.compile(r"^(std::collections::(\w+::)+)HashMap<.+>$") 46STD_HASH_SET_REGEX = re.compile(r"^(std::collections::(\w+::)+)HashSet<.+>$") 47STD_RC_REGEX = re.compile(r"^(alloc::(\w+::)+)Rc<.+>$") 48STD_ARC_REGEX = re.compile(r"^(alloc::(\w+::)+)Arc<.+>$") 49STD_CELL_REGEX = re.compile(r"^(core::(\w+::)+)Cell<.+>$") 50STD_REF_REGEX = re.compile(r"^(core::(\w+::)+)Ref<.+>$") 51STD_REF_MUT_REGEX = re.compile(r"^(core::(\w+::)+)RefMut<.+>$") 52STD_REF_CELL_REGEX = re.compile(r"^(core::(\w+::)+)RefCell<.+>$") 53STD_NONZERO_NUMBER_REGEX = re.compile(r"^core::num::([a-z_]+::)*NonZero.+$") 54 55TUPLE_ITEM_REGEX = re.compile(r"__\d+$") 56 57ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$" 58ENUM_DISR_FIELD_NAME = "<<variant>>" 59 60STD_TYPE_TO_REGEX = { 61 RustType.STD_STRING: STD_STRING_REGEX, 62 RustType.STD_OS_STRING: STD_OS_STRING_REGEX, 63 RustType.STD_STR: STD_STR_REGEX, 64 RustType.STD_SLICE: STD_SLICE_REGEX, 65 RustType.STD_VEC: STD_VEC_REGEX, 66 RustType.STD_VEC_DEQUE: STD_VEC_DEQUE_REGEX, 67 RustType.STD_HASH_MAP: STD_HASH_MAP_REGEX, 68 RustType.STD_HASH_SET: STD_HASH_SET_REGEX, 69 RustType.STD_BTREE_SET: STD_BTREE_SET_REGEX, 70 RustType.STD_BTREE_MAP: STD_BTREE_MAP_REGEX, 71 RustType.STD_RC: STD_RC_REGEX, 72 RustType.STD_ARC: STD_ARC_REGEX, 73 RustType.STD_REF: STD_REF_REGEX, 74 RustType.STD_REF_MUT: STD_REF_MUT_REGEX, 75 RustType.STD_REF_CELL: STD_REF_CELL_REGEX, 76 RustType.STD_CELL: STD_CELL_REGEX, 77 RustType.STD_NONZERO_NUMBER: STD_NONZERO_NUMBER_REGEX, 78} 79 80def is_tuple_fields(fields): 81 # type: (list) -> bool 82 return all(TUPLE_ITEM_REGEX.match(str(field.name)) for field in fields) 83 84 85def classify_struct(name, fields): 86 if len(fields) == 0: 87 return RustType.EMPTY 88 89 for ty, regex in STD_TYPE_TO_REGEX.items(): 90 if regex.match(name): 91 return ty 92 93 if fields[0].name == ENUM_DISR_FIELD_NAME: 94 return RustType.ENUM 95 96 if is_tuple_fields(fields): 97 return RustType.TUPLE 98 99 return RustType.STRUCT 100 101 102def classify_union(fields): 103 if len(fields) == 0: 104 return RustType.EMPTY 105 106 first_variant_name = fields[0].name 107 if first_variant_name is None: 108 if len(fields) == 1: 109 return RustType.SINGLETON_ENUM 110 else: 111 return RustType.REGULAR_ENUM 112 elif first_variant_name.startswith(ENCODED_ENUM_PREFIX): 113 assert len(fields) == 1 114 return RustType.COMPRESSED_ENUM 115 else: 116 return RustType.REGULAR_UNION 117