@@ -1151,6 +1151,129 @@ def has_children(self) -> bool:
1151
1151
return True
1152
1152
1153
1153
1154
+ def children_of_node (node_ptr : SBValue , height : int ):
1155
+ def cast_to_internal (node : SBValue ) -> SBValue :
1156
+ # BTreeMap implementation does ad-hoc polymorphism between LeafNode and InternalNode
1157
+ # with raw pointers.
1158
+ # https://github.com/rust-lang/rust/issues/90520#issuecomment-2211103129
1159
+ internal_type_name = node .type .GetPointeeType ().name .replace (
1160
+ "LeafNode" , "InternalNode" , 1
1161
+ )
1162
+ target = node .GetTarget ()
1163
+ internal_type = target .FindFirstType (internal_type_name )
1164
+ return node .Cast (internal_type .GetPointerType ())
1165
+
1166
+ def unwrap_item_from_array_of_maybe_uninit (arr : SBValue , index : int ) -> SBValue :
1167
+ element = arr .GetChildAtIndex (index )
1168
+ return element .GetChildMemberWithName ("value" ).GetChildMemberWithName ("value" )
1169
+
1170
+ if node_ptr .type .name .startswith ("alloc::collections::btree::node::BoxedNode<" ):
1171
+ # BACKCOMPAT: rust 1.49
1172
+ node_ptr = node_ptr .GetChildMemberWithName ("ptr" )
1173
+ node_ptr = unwrap_unique_or_non_null (node_ptr )
1174
+ leaf = node_ptr .Dereference ()
1175
+ keys = leaf .GetChildMemberWithName ("keys" )
1176
+ vals = leaf .GetChildMemberWithName ("vals" )
1177
+ length = leaf .GetChildMemberWithName ("len" ).unsigned
1178
+ edges = (
1179
+ cast_to_internal (node_ptr ).GetChildMemberWithName ("edges" )
1180
+ if height > 0
1181
+ else None
1182
+ )
1183
+
1184
+ for i in range (length + 1 ):
1185
+ if height > 0 :
1186
+ child_ptr = unwrap_item_from_array_of_maybe_uninit (edges , i )
1187
+ yield from children_of_node (child_ptr , height - 1 )
1188
+ if i < length :
1189
+ # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
1190
+ key_type_size = keys .type .size
1191
+ val_type_size = vals .type .size
1192
+ key = (
1193
+ unwrap_item_from_array_of_maybe_uninit (keys , i )
1194
+ if key_type_size > 0
1195
+ else node_ptr .EvaluateExpression ("()" )
1196
+ )
1197
+ val = (
1198
+ unwrap_item_from_array_of_maybe_uninit (vals , i )
1199
+ if val_type_size > 0
1200
+ else node_ptr .EvaluateExpression ("()" )
1201
+ )
1202
+ yield key , val
1203
+
1204
+
1205
+ def strip_till_parentheses (text : str ) -> str :
1206
+ start = text .find ("(" )
1207
+ end = text .find (")" )
1208
+ if start == - 1 or end == - 1 :
1209
+ return text
1210
+ return text [start : end + 1 ]
1211
+
1212
+
1213
+ class StdBTreeMapSyntheticProvider :
1214
+ def __init__ (self , valobj : SBValue , _dict : LLDBOpaque , show_values : bool = True ):
1215
+ self .valobj = valobj
1216
+ self ._dict = _dict
1217
+ self .show_values = True
1218
+
1219
+ def num_children (self ) -> int :
1220
+ return self .size
1221
+
1222
+ def get_child_index (self , name : str ) -> int :
1223
+ index = name .lstrip ("[" ).rstrip ("]" )
1224
+ if index .isdigit ():
1225
+ return int (index )
1226
+ else :
1227
+ return - 1
1228
+
1229
+ def get_child_at_index (self , index : int ) -> SBValue :
1230
+ key , value = self .items [index ]
1231
+ if self .show_values :
1232
+ data = key .GetData ()
1233
+ assert data .Append (value .GetData ()), "Failed to create key value pair"
1234
+ return self .valobj .CreateValueFromData ("[%s]" % index , data , self .pair_type )
1235
+ return self .valobj .CreateValueFromData ("[%s]" % index , key .GetData (), key .type )
1236
+
1237
+ def update (self ) -> bool :
1238
+ self .size = self .valobj .GetChildMemberWithName ("length" ).unsigned
1239
+ self .items = []
1240
+
1241
+ # Determine the type for the tuple (Key, Value)
1242
+ # - get_template_args helper breaks on console because type is shown as
1243
+ # `core::marker::PhantomData<(&str, &str) *>`
1244
+ # - Type lookup after get_template_args helper fails with codelldb for unclear reasons
1245
+ # - Native `template_args[0]` from LLDB fails with codelldb and just says `T` if printed
1246
+ # on console
1247
+ marker_type_name = self .valobj .GetChildMemberWithName ("_marker" ).GetTypeName ()
1248
+ pair_type_name = strip_till_parentheses (marker_type_name )
1249
+ target = self .valobj .GetTarget ()
1250
+ self .pair_type = target .FindFirstType (pair_type_name )
1251
+
1252
+ if self .size == 0 :
1253
+ return
1254
+
1255
+ root = self .valobj .GetChildMemberWithName ("root" )
1256
+
1257
+ if root .type .name .startswith ("core::option::Option<" ):
1258
+ target = self .valobj .GetTarget ()
1259
+ type_some = target .FindFirstType (get_template_args (root .GetTypeName ())[0 ])
1260
+ root = root .Cast (type_some )
1261
+
1262
+ height = root .GetChildMemberWithName ("height" )
1263
+ node_ptr = root .GetChildMemberWithName ("node" )
1264
+
1265
+ self .items = [
1266
+ (key , value ) for key , value in children_of_node (node_ptr , height .unsigned )
1267
+ ]
1268
+
1269
+ assert len (self .items ) == self .size
1270
+
1271
+ return False
1272
+
1273
+ def has_children (self ) -> bool :
1274
+ return True
1275
+
1276
+
1154
1277
def StdRcSummaryProvider (valobj : SBValue , _dict : LLDBOpaque ) -> str :
1155
1278
strong = valobj .GetChildMemberWithName ("strong" ).GetValueAsUnsigned ()
1156
1279
weak = valobj .GetChildMemberWithName ("weak" ).GetValueAsUnsigned ()
0 commit comments