]> git.proxmox.com Git - rustc.git/blob - src/etc/lldb_providers.py
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / src / etc / lldb_providers.py
1 import sys
2
3 from lldb import SBValue, SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \
4 eBasicTypeUnsignedChar
5
6 # from lldb.formatters import Logger
7
8 ####################################################################################################
9 # This file contains two kinds of pretty-printers: summary and synthetic.
10 #
11 # Important classes from LLDB module:
12 # SBValue: the value of a variable, a register, or an expression
13 # SBType: the data type; each SBValue has a corresponding SBType
14 #
15 # Summary provider is a function with the type `(SBValue, dict) -> str`.
16 # The first parameter is the object encapsulating the actual variable being displayed;
17 # The second parameter is an internal support parameter used by LLDB, and you should not touch it.
18 #
19 # Synthetic children is the way to provide a children-based representation of the object's value.
20 # Synthetic provider is a class that implements the following interface:
21 #
22 # class SyntheticChildrenProvider:
23 # def __init__(self, SBValue, dict)
24 # def num_children(self)
25 # def get_child_index(self, str)
26 # def get_child_at_index(self, int)
27 # def update(self)
28 # def has_children(self)
29 # def get_value(self)
30 #
31 #
32 # You can find more information and examples here:
33 # 1. https://lldb.llvm.org/varformats.html
34 # 2. https://lldb.llvm.org/python-reference.html
35 # 3. https://lldb.llvm.org/python_reference/lldb.formatters.cpp.libcxx-pysrc.html
36 # 4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa
37 ####################################################################################################
38
39 PY3 = sys.version_info[0] == 3
40
41
42 class ValueBuilder:
43 def __init__(self, valobj):
44 # type: (SBValue) -> ValueBuilder
45 self.valobj = valobj
46 process = valobj.GetProcess()
47 self.endianness = process.GetByteOrder()
48 self.pointer_size = process.GetAddressByteSize()
49
50 def from_int(self, name, value):
51 # type: (str, int) -> SBValue
52 type = self.valobj.GetType().GetBasicType(eBasicTypeLong)
53 data = SBData.CreateDataFromSInt64Array(self.endianness, self.pointer_size, [value])
54 return self.valobj.CreateValueFromData(name, data, type)
55
56 def from_uint(self, name, value):
57 # type: (str, int) -> SBValue
58 type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong)
59 data = SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [value])
60 return self.valobj.CreateValueFromData(name, data, type)
61
62
63 def unwrap_unique_or_non_null(unique_or_nonnull):
64 # BACKCOMPAT: rust 1.32
65 # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
66 ptr = unique_or_nonnull.GetChildMemberWithName("pointer")
67 return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0)
68
69
70 class DefaultSynthteticProvider:
71 def __init__(self, valobj, dict):
72 # type: (SBValue, dict) -> DefaultSynthteticProvider
73 # logger = Logger.Logger()
74 # logger >> "Default synthetic provider for " + str(valobj.GetName())
75 self.valobj = valobj
76
77 def num_children(self):
78 # type: () -> int
79 return self.valobj.GetNumChildren()
80
81 def get_child_index(self, name):
82 # type: (str) -> int
83 return self.valobj.GetIndexOfChildWithName(name)
84
85 def get_child_at_index(self, index):
86 # type: (int) -> SBValue
87 return self.valobj.GetChildAtIndex(index)
88
89 def update(self):
90 # type: () -> None
91 pass
92
93 def has_children(self):
94 # type: () -> bool
95 return self.valobj.MightHaveChildren()
96
97
98 class EmptySyntheticProvider:
99 def __init__(self, valobj, dict):
100 # type: (SBValue, dict) -> EmptySyntheticProvider
101 # logger = Logger.Logger()
102 # logger >> "[EmptySyntheticProvider] for " + str(valobj.GetName())
103 self.valobj = valobj
104
105 def num_children(self):
106 # type: () -> int
107 return 0
108
109 def get_child_index(self, name):
110 # type: (str) -> int
111 return None
112
113 def get_child_at_index(self, index):
114 # type: (int) -> SBValue
115 return None
116
117 def update(self):
118 # type: () -> None
119 pass
120
121 def has_children(self):
122 # type: () -> bool
123 return False
124
125
126 def SizeSummaryProvider(valobj, dict):
127 # type: (SBValue, dict) -> str
128 return 'size=' + str(valobj.GetNumChildren())
129
130
131 def vec_to_string(vec):
132 length = vec.GetNumChildren()
133 chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)]
134 return bytes(chars).decode(errors='replace') if PY3 else "".join(chr(char) for char in chars)
135
136
137 def StdStringSummaryProvider(valobj, dict):
138 # type: (SBValue, dict) -> str
139 # logger = Logger.Logger()
140 # logger >> "[StdStringSummaryProvider] for " + str(valobj.GetName())
141 vec = valobj.GetChildAtIndex(0)
142 return '"%s"' % vec_to_string(vec)
143
144
145 def StdOsStringSummaryProvider(valobj, dict):
146 # type: (SBValue, dict) -> str
147 # logger = Logger.Logger()
148 # logger >> "[StdOsStringSummaryProvider] for " + str(valobj.GetName())
149 buf = valobj.GetChildAtIndex(0).GetChildAtIndex(0)
150 is_windows = "Wtf8Buf" in buf.type.name
151 vec = buf.GetChildAtIndex(0) if is_windows else buf
152 return '"%s"' % vec_to_string(vec)
153
154
155 def StdStrSummaryProvider(valobj, dict):
156 # type: (SBValue, dict) -> str
157 # logger = Logger.Logger()
158 # logger >> "[StdStrSummaryProvider] for " + str(valobj.GetName())
159
160 length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned()
161 if length == 0:
162 return '""'
163
164 data_ptr = valobj.GetChildMemberWithName("data_ptr")
165
166 start = data_ptr.GetValueAsUnsigned()
167 error = SBError()
168 process = data_ptr.GetProcess()
169 data = process.ReadMemory(start, length, error)
170 data = data.decode(encoding='UTF-8') if PY3 else data
171 return '"%s"' % data
172
173
174 class StructSyntheticProvider:
175 """Pretty-printer for structs and struct enum variants"""
176
177 def __init__(self, valobj, dict, is_variant=False):
178 # type: (SBValue, dict, bool) -> StructSyntheticProvider
179 # logger = Logger.Logger()
180 self.valobj = valobj
181 self.is_variant = is_variant
182 self.type = valobj.GetType()
183 self.fields = {}
184
185 if is_variant:
186 self.fields_count = self.type.GetNumberOfFields() - 1
187 real_fields = self.type.fields[1:]
188 else:
189 self.fields_count = self.type.GetNumberOfFields()
190 real_fields = self.type.fields
191
192 for number, field in enumerate(real_fields):
193 self.fields[field.name] = number
194
195 def num_children(self):
196 # type: () -> int
197 return self.fields_count
198
199 def get_child_index(self, name):
200 # type: (str) -> int
201 return self.fields.get(name, -1)
202
203 def get_child_at_index(self, index):
204 # type: (int) -> SBValue
205 if self.is_variant:
206 field = self.type.GetFieldAtIndex(index + 1)
207 else:
208 field = self.type.GetFieldAtIndex(index)
209 return self.valobj.GetChildMemberWithName(field.name)
210
211 def update(self):
212 # type: () -> None
213 pass
214
215 def has_children(self):
216 # type: () -> bool
217 return True
218
219
220 class TupleSyntheticProvider:
221 """Pretty-printer for tuples and tuple enum variants"""
222
223 def __init__(self, valobj, dict, is_variant=False):
224 # type: (SBValue, dict, bool) -> TupleSyntheticProvider
225 # logger = Logger.Logger()
226 self.valobj = valobj
227 self.is_variant = is_variant
228 self.type = valobj.GetType()
229
230 if is_variant:
231 self.size = self.type.GetNumberOfFields() - 1
232 else:
233 self.size = self.type.GetNumberOfFields()
234
235 def num_children(self):
236 # type: () -> int
237 return self.size
238
239 def get_child_index(self, name):
240 # type: (str) -> int
241 if name.isdigit():
242 return int(name)
243 else:
244 return -1
245
246 def get_child_at_index(self, index):
247 # type: (int) -> SBValue
248 if self.is_variant:
249 field = self.type.GetFieldAtIndex(index + 1)
250 else:
251 field = self.type.GetFieldAtIndex(index)
252 element = self.valobj.GetChildMemberWithName(field.name)
253 return self.valobj.CreateValueFromData(str(index), element.GetData(), element.GetType())
254
255 def update(self):
256 # type: () -> None
257 pass
258
259 def has_children(self):
260 # type: () -> bool
261 return True
262
263
264 class StdVecSyntheticProvider:
265 """Pretty-printer for alloc::vec::Vec<T>
266
267 struct Vec<T> { buf: RawVec<T>, len: usize }
268 struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
269 rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... }
270 rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
271 struct NonZero<T>(T)
272 """
273
274 def __init__(self, valobj, dict):
275 # type: (SBValue, dict) -> StdVecSyntheticProvider
276 # logger = Logger.Logger()
277 # logger >> "[StdVecSyntheticProvider] for " + str(valobj.GetName())
278 self.valobj = valobj
279 self.update()
280
281 def num_children(self):
282 # type: () -> int
283 return self.length
284
285 def get_child_index(self, name):
286 # type: (str) -> int
287 index = name.lstrip('[').rstrip(']')
288 if index.isdigit():
289 return int(index)
290 else:
291 return -1
292
293 def get_child_at_index(self, index):
294 # type: (int) -> SBValue
295 start = self.data_ptr.GetValueAsUnsigned()
296 address = start + index * self.element_type_size
297 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
298 return element
299
300 def update(self):
301 # type: () -> None
302 self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
303 self.buf = self.valobj.GetChildMemberWithName("buf")
304
305 self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
306
307 self.element_type = self.data_ptr.GetType().GetPointeeType()
308 self.element_type_size = self.element_type.GetByteSize()
309
310 def has_children(self):
311 # type: () -> bool
312 return True
313
314
315 class StdSliceSyntheticProvider:
316 def __init__(self, valobj, dict):
317 self.valobj = valobj
318 self.update()
319
320 def num_children(self):
321 # type: () -> int
322 return self.length
323
324 def get_child_index(self, name):
325 # type: (str) -> int
326 index = name.lstrip('[').rstrip(']')
327 if index.isdigit():
328 return int(index)
329 else:
330 return -1
331
332 def get_child_at_index(self, index):
333 # type: (int) -> SBValue
334 start = self.data_ptr.GetValueAsUnsigned()
335 address = start + index * self.element_type_size
336 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
337 return element
338
339 def update(self):
340 # type: () -> None
341 self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned()
342 self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr")
343
344 self.element_type = self.data_ptr.GetType().GetPointeeType()
345 self.element_type_size = self.element_type.GetByteSize()
346
347 def has_children(self):
348 # type: () -> bool
349 return True
350
351
352 class StdVecDequeSyntheticProvider:
353 """Pretty-printer for alloc::collections::vec_deque::VecDeque<T>
354
355 struct VecDeque<T> { tail: usize, head: usize, buf: RawVec<T> }
356 """
357
358 def __init__(self, valobj, dict):
359 # type: (SBValue, dict) -> StdVecDequeSyntheticProvider
360 # logger = Logger.Logger()
361 # logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName())
362 self.valobj = valobj
363 self.update()
364
365 def num_children(self):
366 # type: () -> int
367 return self.size
368
369 def get_child_index(self, name):
370 # type: (str) -> int
371 index = name.lstrip('[').rstrip(']')
372 if index.isdigit() and self.tail <= index and (self.tail + index) % self.cap < self.head:
373 return int(index)
374 else:
375 return -1
376
377 def get_child_at_index(self, index):
378 # type: (int) -> SBValue
379 start = self.data_ptr.GetValueAsUnsigned()
380 address = start + ((index + self.tail) % self.cap) * self.element_type_size
381 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
382 return element
383
384 def update(self):
385 # type: () -> None
386 self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned()
387 self.tail = self.valobj.GetChildMemberWithName("tail").GetValueAsUnsigned()
388 self.buf = self.valobj.GetChildMemberWithName("buf")
389 self.cap = self.buf.GetChildMemberWithName("cap").GetValueAsUnsigned()
390 if self.head >= self.tail:
391 self.size = self.head - self.tail
392 else:
393 self.size = self.cap + self.head - self.tail
394
395 self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
396
397 self.element_type = self.data_ptr.GetType().GetPointeeType()
398 self.element_type_size = self.element_type.GetByteSize()
399
400 def has_children(self):
401 # type: () -> bool
402 return True
403
404
405 # BACKCOMPAT: rust 1.35
406 class StdOldHashMapSyntheticProvider:
407 """Pretty-printer for std::collections::hash::map::HashMap<K, V, S>
408
409 struct HashMap<K, V, S> {..., table: RawTable<K, V>, ... }
410 struct RawTable<K, V> { capacity_mask: usize, size: usize, hashes: TaggedHashUintPtr, ... }
411 """
412
413 def __init__(self, valobj, dict, show_values=True):
414 # type: (SBValue, dict, bool) -> StdOldHashMapSyntheticProvider
415 self.valobj = valobj
416 self.show_values = show_values
417 self.update()
418
419 def num_children(self):
420 # type: () -> int
421 return self.size
422
423 def get_child_index(self, name):
424 # type: (str) -> int
425 index = name.lstrip('[').rstrip(']')
426 if index.isdigit():
427 return int(index)
428 else:
429 return -1
430
431 def get_child_at_index(self, index):
432 # type: (int) -> SBValue
433 # logger = Logger.Logger()
434 start = self.data_ptr.GetValueAsUnsigned() & ~1
435
436 # See `libstd/collections/hash/table.rs:raw_bucket_at
437 hashes = self.hash_uint_size * self.capacity
438 align = self.pair_type_size
439 # See `libcore/alloc.rs:padding_needed_for`
440 len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~(
441 (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo
442 # len_rounded_up = ((hashes + align - 1) & ~(align - 1)) - hashes
443
444 pairs_offset = hashes + len_rounded_up
445 pairs_start = start + pairs_offset
446
447 table_index = self.valid_indices[index]
448 idx = table_index & self.capacity_mask
449 address = pairs_start + idx * self.pair_type_size
450 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
451 if self.show_values:
452 return element
453 else:
454 key = element.GetChildAtIndex(0)
455 return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
456
457 def update(self):
458 # type: () -> None
459 # logger = Logger.Logger()
460
461 self.table = self.valobj.GetChildMemberWithName("table") # type: SBValue
462 self.size = self.table.GetChildMemberWithName("size").GetValueAsUnsigned()
463 self.hashes = self.table.GetChildMemberWithName("hashes")
464 self.hash_uint_type = self.hashes.GetType()
465 self.hash_uint_size = self.hashes.GetType().GetByteSize()
466 self.modulo = 2 ** self.hash_uint_size
467 self.data_ptr = self.hashes.GetChildAtIndex(0).GetChildAtIndex(0)
468
469 self.capacity_mask = self.table.GetChildMemberWithName("capacity_mask").GetValueAsUnsigned()
470 self.capacity = (self.capacity_mask + 1) % self.modulo
471
472 marker = self.table.GetChildMemberWithName("marker").GetType() # type: SBType
473 self.pair_type = marker.template_args[0]
474 self.pair_type_size = self.pair_type.GetByteSize()
475
476 self.valid_indices = []
477 for idx in range(self.capacity):
478 address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size
479 hash_uint = self.data_ptr.CreateValueFromAddress("[%s]" % idx, address,
480 self.hash_uint_type)
481 hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0)
482 if hash_ptr.GetValueAsUnsigned() != 0:
483 self.valid_indices.append(idx)
484
485 # logger >> "Valid indices: {}".format(str(self.valid_indices))
486
487 def has_children(self):
488 # type: () -> bool
489 return True
490
491
492 class StdHashMapSyntheticProvider:
493 """Pretty-printer for hashbrown's HashMap"""
494
495 def __init__(self, valobj, dict, show_values=True):
496 # type: (SBValue, dict, bool) -> StdHashMapSyntheticProvider
497 self.valobj = valobj
498 self.show_values = show_values
499 self.update()
500
501 def num_children(self):
502 # type: () -> int
503 return self.size
504
505 def get_child_index(self, name):
506 # type: (str) -> int
507 index = name.lstrip('[').rstrip(']')
508 if index.isdigit():
509 return int(index)
510 else:
511 return -1
512
513 def get_child_at_index(self, index):
514 # type: (int) -> SBValue
515 pairs_start = self.data_ptr.GetValueAsUnsigned()
516 idx = self.valid_indices[index]
517 if self.new_layout:
518 idx = -(idx + 1)
519 address = pairs_start + idx * self.pair_type_size
520 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
521 if self.show_values:
522 return element
523 else:
524 key = element.GetChildAtIndex(0)
525 return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
526
527 def update(self):
528 # type: () -> None
529 table = self.table()
530 capacity = table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
531 ctrl = table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)
532
533 self.size = table.GetChildMemberWithName("items").GetValueAsUnsigned()
534 self.pair_type = table.type.template_args[0]
535 self.pair_type_size = self.pair_type.GetByteSize()
536
537 self.new_layout = not table.GetChildMemberWithName("data").IsValid()
538 if self.new_layout:
539 self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType())
540 else:
541 self.data_ptr = table.GetChildMemberWithName("data").GetChildAtIndex(0)
542
543 u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar)
544 u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()
545
546 self.valid_indices = []
547 for idx in range(capacity):
548 address = ctrl.GetValueAsUnsigned() + idx * u8_type_size
549 value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address,
550 u8_type).GetValueAsUnsigned()
551 is_present = value & 128 == 0
552 if is_present:
553 self.valid_indices.append(idx)
554
555 def table(self):
556 # type: () -> SBValue
557 if self.show_values:
558 hashbrown_hashmap = self.valobj.GetChildMemberWithName("base")
559 else:
560 # BACKCOMPAT: rust 1.47
561 # HashSet wraps either std HashMap or hashbrown::HashSet, which both
562 # wrap hashbrown::HashMap, so either way we "unwrap" twice.
563 hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0)
564 return hashbrown_hashmap.GetChildMemberWithName("table")
565
566 def has_children(self):
567 # type: () -> bool
568 return True
569
570
571 def StdRcSummaryProvider(valobj, dict):
572 # type: (SBValue, dict) -> str
573 strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned()
574 weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned()
575 return "strong={}, weak={}".format(strong, weak)
576
577
578 class StdRcSyntheticProvider:
579 """Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T>
580
581 struct Rc<T> { ptr: NonNull<RcBox<T>>, ... }
582 rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> }
583 rust 1.33.0: struct NonNull<T> { pointer: *const T }
584 struct NonZero<T>(T)
585 struct RcBox<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }
586 struct Cell<T> { value: UnsafeCell<T> }
587 struct UnsafeCell<T> { value: T }
588
589 struct Arc<T> { ptr: NonNull<ArcInner<T>>, ... }
590 struct ArcInner<T> { strong: atomic::AtomicUsize, weak: atomic::AtomicUsize, data: T }
591 struct AtomicUsize { v: UnsafeCell<usize> }
592 """
593
594 def __init__(self, valobj, dict, is_atomic=False):
595 # type: (SBValue, dict, bool) -> StdRcSyntheticProvider
596 self.valobj = valobj
597
598 self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr"))
599
600 self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value")
601
602 self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex(
603 0).GetChildMemberWithName("value")
604 self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex(
605 0).GetChildMemberWithName("value")
606
607 self.value_builder = ValueBuilder(valobj)
608
609 self.update()
610
611 def num_children(self):
612 # type: () -> int
613 # Actually there are 3 children, but only the `value` should be shown as a child
614 return 1
615
616 def get_child_index(self, name):
617 # type: (str) -> int
618 if name == "value":
619 return 0
620 if name == "strong":
621 return 1
622 if name == "weak":
623 return 2
624 return -1
625
626 def get_child_at_index(self, index):
627 # type: (int) -> SBValue
628 if index == 0:
629 return self.value
630 if index == 1:
631 return self.value_builder.from_uint("strong", self.strong_count)
632 if index == 2:
633 return self.value_builder.from_uint("weak", self.weak_count)
634
635 return None
636
637 def update(self):
638 # type: () -> None
639 self.strong_count = self.strong.GetValueAsUnsigned()
640 self.weak_count = self.weak.GetValueAsUnsigned() - 1
641
642 def has_children(self):
643 # type: () -> bool
644 return True
645
646
647 class StdCellSyntheticProvider:
648 """Pretty-printer for std::cell::Cell"""
649
650 def __init__(self, valobj, dict):
651 # type: (SBValue, dict) -> StdCellSyntheticProvider
652 self.valobj = valobj
653 self.value = valobj.GetChildMemberWithName("value").GetChildAtIndex(0)
654
655 def num_children(self):
656 # type: () -> int
657 return 1
658
659 def get_child_index(self, name):
660 # type: (str) -> int
661 if name == "value":
662 return 0
663 return -1
664
665 def get_child_at_index(self, index):
666 # type: (int) -> SBValue
667 if index == 0:
668 return self.value
669 return None
670
671 def update(self):
672 # type: () -> None
673 pass
674
675 def has_children(self):
676 # type: () -> bool
677 return True
678
679
680 def StdRefSummaryProvider(valobj, dict):
681 # type: (SBValue, dict) -> str
682 borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned()
683 return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
684
685
686 class StdRefSyntheticProvider:
687 """Pretty-printer for std::cell::Ref, std::cell::RefMut, and std::cell::RefCell"""
688
689 def __init__(self, valobj, dict, is_cell=False):
690 # type: (SBValue, dict, bool) -> StdRefSyntheticProvider
691 self.valobj = valobj
692
693 borrow = valobj.GetChildMemberWithName("borrow")
694 value = valobj.GetChildMemberWithName("value")
695 if is_cell:
696 self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName("value")
697 self.value = value.GetChildMemberWithName("value")
698 else:
699 self.borrow = borrow.GetChildMemberWithName("borrow").GetChildMemberWithName(
700 "value").GetChildMemberWithName("value")
701 self.value = value.Dereference()
702
703 self.value_builder = ValueBuilder(valobj)
704
705 self.update()
706
707 def num_children(self):
708 # type: () -> int
709 # Actually there are 2 children, but only the `value` should be shown as a child
710 return 1
711
712 def get_child_index(self, name):
713 if name == "value":
714 return 0
715 if name == "borrow":
716 return 1
717 return -1
718
719 def get_child_at_index(self, index):
720 # type: (int) -> SBValue
721 if index == 0:
722 return self.value
723 if index == 1:
724 return self.value_builder.from_int("borrow", self.borrow_count)
725 return None
726
727 def update(self):
728 # type: () -> None
729 self.borrow_count = self.borrow.GetValueAsSigned()
730
731 def has_children(self):
732 # type: () -> bool
733 return True