@@ -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 = cast_to_internal (node_ptr ).GetChildMemberWithName ("edges" ) if height > 0 else None
1179
+
1180
+ for i in range (length + 1 ):
1181
+ if height > 0 :
1182
+ child_ptr = unwrap_item_from_array_of_maybe_uninit (edges , i )
1183
+ yield from children_of_node (child_ptr , height - 1 )
1184
+ if i < length :
1185
+ # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
1186
+ key_type_size = keys .type .size
1187
+ val_type_size = vals .type .size
1188
+ key = (
1189
+ unwrap_item_from_array_of_maybe_uninit (keys , i )
1190
+ if key_type_size > 0
1191
+ else node_ptr .EvaluateExpression ("()" )
1192
+ )
1193
+ val = (
1194
+ unwrap_item_from_array_of_maybe_uninit (vals , i )
1195
+ if val_type_size > 0
1196
+ else node_ptr .EvaluateExpression ("()" )
1197
+ )
1198
+ yield key , val
1199
+
1200
+ def strip_till_parentheses (text : str ) -> str :
1201
+ start = text .find ('(' )
1202
+ end = text .find (')' )
1203
+ if start == - 1 or end == - 1 :
1204
+ return text
1205
+ return text [start : end + 1 ]
1206
+
1207
+
1208
+ class StdBTreeMapSyntheticProvider :
1209
+ def __init__ (self , valobj : SBValue , _dict : LLDBOpaque , show_values : bool = True ):
1210
+ self .valobj = valobj
1211
+ self ._dict = _dict
1212
+ self .show_values = True
1213
+
1214
+ def num_children (self ) -> int :
1215
+ return self .size
1216
+
1217
+ def get_child_index (self , name : str ) -> int :
1218
+ index = name .lstrip ("[" ).rstrip ("]" )
1219
+ if index .isdigit ():
1220
+ return int (index )
1221
+ else :
1222
+ return - 1
1223
+
1224
+ def get_child_at_index (self , index : int ) -> SBValue :
1225
+ key , value = self .items [index ]
1226
+ if self .show_values :
1227
+ data = key .GetData ()
1228
+ assert data .Append (value .GetData ()), "Failed to create key value pair"
1229
+ return self .valobj .CreateValueFromData (
1230
+ "[%s]" % index , data , self .pair_type
1231
+ )
1232
+ return self .valobj .CreateValueFromData (
1233
+ "[%s]" % index , key .GetData (), key .type
1234
+ )
1235
+
1236
+ def update (self ) -> bool :
1237
+ self .size = self .valobj .GetChildMemberWithName ("length" ).unsigned
1238
+ self .items = []
1239
+
1240
+ # Determine the type for the tuple (Key, Value)
1241
+ # - get_template_args helper breaks on console because type is shown as
1242
+ # `core::marker::PhantomData<(&str, &str) *>`
1243
+ # - Type lookup after get_template_args helper fails with codelldb for unclear reasons
1244
+ # - Native `template_args[0]` from LLDB fails with codelldb and just says `T` if printed
1245
+ # on console
1246
+ marker_type_name = self .valobj .GetChildMemberWithName ("_marker" ).GetTypeName ()
1247
+ pair_type_name = strip_till_parentheses (marker_type_name )
1248
+ target = self .valobj .GetTarget ()
1249
+ self .pair_type = target .FindFirstType (pair_type_name )
1250
+
1251
+ if self .size == 0 :
1252
+ return
1253
+
1254
+ root = self .valobj .GetChildMemberWithName ("root" )
1255
+
1256
+ if root .type .name .startswith ("core::option::Option<" ):
1257
+ target = self .valobj .GetTarget ()
1258
+ type_some = target .FindFirstType (get_template_args (root .GetTypeName ())[0 ])
1259
+ root = root .Cast (type_some )
1260
+
1261
+ height = root .GetChildMemberWithName ("height" )
1262
+ node_ptr = root .GetChildMemberWithName ("node" )
1263
+
1264
+ self .items = [
1265
+ (key , value )
1266
+ 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