xref: /llvm-project/lldb/test/API/lang/rust/enum-structs/RustEnumValue.py (revision 6bf923d5c3daf5d66e0acf53d037a12ceff4a275)
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