repo_description: Empowering everyone to build reliable and efficient software.
repo_topics: compiler language rust
code: 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
  