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