1"""Helper library to traverse data emitted for Rust enums """ 2from lldbsuite.test.lldbtest import * 3 4DISCRIMINANT_MEMBER_NAME = "$discr$" 5VALUE_MEMBER_NAME = "value" 6 7 8class RustEnumValue: 9 def __init__(self, value: lldb.SBValue): 10 self.value = value 11 12 def getAllVariantTypes(self): 13 result = [] 14 for i in range(self._inner().GetNumChildren()): 15 result.append(self.getVariantByIndex(i).GetDisplayTypeName()) 16 return result 17 18 def _inner(self) -> lldb.SBValue: 19 return self.value.GetChildAtIndex(0) 20 21 def getVariantByIndex(self, index): 22 return ( 23 self._inner() 24 .GetChildAtIndex(index) 25 .GetChildMemberWithName(VALUE_MEMBER_NAME) 26 ) 27 28 @staticmethod 29 def _getDiscriminantValueAsUnsigned(discr_sbvalue: lldb.SBValue): 30 byte_size = discr_sbvalue.GetType().GetByteSize() 31 error = lldb.SBError() 32 33 # when discriminant is u16 Clang emits 'unsigned char' 34 # and LLDB seems to treat it as character type disalowing to call GetValueAsUnsigned 35 if byte_size == 1: 36 return discr_sbvalue.GetData().GetUnsignedInt8(error, 0) 37 elif byte_size == 2: 38 return discr_sbvalue.GetData().GetUnsignedInt16(error, 0) 39 elif byte_size == 4: 40 return discr_sbvalue.GetData().GetUnsignedInt32(error, 0) 41 elif byte_size == 8: 42 return discr_sbvalue.GetData().GetUnsignedInt64(error, 0) 43 else: 44 return discr_sbvalue.GetValueAsUnsigned() 45 46 def getCurrentVariantIndex(self): 47 default_index = 0 48 for i in range(self._inner().GetNumChildren()): 49 variant: lldb.SBValue = self._inner().GetChildAtIndex(i) 50 discr = variant.GetChildMemberWithName(DISCRIMINANT_MEMBER_NAME) 51 if discr.IsValid(): 52 discr_unsigned_value = RustEnumValue._getDiscriminantValueAsUnsigned( 53 discr 54 ) 55 if variant.GetName() == f"$variant${discr_unsigned_value}": 56 return discr_unsigned_value 57 else: 58 default_index = i 59 return default_index 60 61 def getFields(self): 62 result = [] 63 for i in range(self._inner().GetNumChildren()): 64 type: lldb.SBType = self._inner().GetType() 65 result.append(type.GetFieldAtIndex(i).GetName()) 66 return result 67 68 def getCurrentValue(self) -> lldb.SBValue: 69 return self.getVariantByIndex(self.getCurrentVariantIndex()) 70