| <?xml version="1.0" encoding="utf-8"?> | |
| <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> | |
| <!-- | |
| std::collection::Hash* container visualizers | |
| Current std impls: | |
| std::collections::hash::set::HashSet<K, S> is implemented in terms of... | |
| hashbrown::set::HashSet<K, S> is implemented in terms of... | |
| hashbrown::map::HashMap<K, V, S> is implemented in terms of... | |
| hashbrown::raw::RawTable<(K, V)> | |
| Ideally, we'd teach rustc to scan dependencies/crates for .natvis files so | |
| the bulk of this could live alongside the hashbrown crate implementation, | |
| and std would just forward using e.g. <ExpandedItem>base</ExpandedItem>. | |
| However, Given that std...Hash*Set* is currently implemented in terms of | |
| hashbrown...Hash*Map*, which would visualize poorly, we want to customize the | |
| look/feel at the std type level *anyways*... | |
| References: | |
| https://github.com/rust-lang/rust/blob/HEAD/src/libstd/collections/hash/map.rs | |
| https://github.com/rust-lang/rust/blob/HEAD/src/libstd/collections/hash/set.rs | |
| https://github.com/rust-lang/hashbrown/blob/master/src/map.rs | |
| https://github.com/rust-lang/hashbrown/blob/master/src/set.rs | |
| https://github.com/rust-lang/hashbrown/blob/master/src/raw/mod.rs | |
| --> | |
| <Type Name="std::collections::hash::map::HashMap<*,*,*>"> | |
| <DisplayString>{{ len={base.table.table.items} }}</DisplayString> | |
| <Expand> | |
| <Item Name="[len]">base.table.table.items</Item> | |
| <Item Name="[capacity]">base.table.table.items + base.table.table.growth_left</Item> | |
| <Item Name="[state]">base.hash_builder</Item> | |
| <CustomListItems> | |
| <Variable Name="i" InitialValue="0" /> | |
| <Variable Name="n" InitialValue="base.table.table.items" /> | |
| <Size>base.table.table.items</Size> | |
| <Loop> | |
| <Break Condition="n == 0" /> | |
| <If Condition="(base.table.table.ctrl.pointer[i] & 0x80) == 0"> | |
| <!-- Bucket is populated --> | |
| <Exec>n--</Exec> | |
| <Item Name="{((tuple$<$T1,$T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple$<$T1,$T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item> | |
| </If> | |
| <Exec>i++</Exec> | |
| </Loop> | |
| </CustomListItems> | |
| </Expand> | |
| </Type> | |
| <Type Name="std::collections::hash::set::HashSet<*,*>"> | |
| <DisplayString>{{ len={base.map.table.table.items} }}</DisplayString> | |
| <Expand> | |
| <Item Name="[len]">base.map.table.table.items</Item> | |
| <Item Name="[capacity]">base.map.table.table.items + base.map.table.table.growth_left</Item> | |
| <Item Name="[state]">base.map.hash_builder</Item> | |
| <CustomListItems> | |
| <Variable Name="i" InitialValue="0" /> | |
| <Variable Name="n" InitialValue="base.map.table.table.items" /> | |
| <Size>base.map.table.table.items</Size> | |
| <Loop> | |
| <Break Condition="n == 0" /> | |
| <If Condition="(base.map.table.table.ctrl.pointer[i] & 0x80) == 0"> | |
| <!-- Bucket is populated --> | |
| <Exec>n--</Exec> | |
| <Item>(($T1*)base.map.table.table.ctrl.pointer)[-(i + 1)]</Item> | |
| </If> | |
| <Exec>i++</Exec> | |
| </Loop> | |
| </CustomListItems> | |
| </Expand> | |
| </Type> | |
| <Type Name="std::ffi::c_str::CString"> | |
| <DisplayString>{(char*)inner.data_ptr}</DisplayString> | |
| <Expand> | |
| <Synthetic Name="[chars]"> | |
| <DisplayString>{(char*)inner.data_ptr}</DisplayString> | |
| <Expand> | |
| <ArrayItems> | |
| <Size>inner.length</Size> | |
| <ValuePointer>(char*)inner.data_ptr</ValuePointer> | |
| </ArrayItems> | |
| </Expand> | |
| </Synthetic> | |
| </Expand> | |
| </Type> | |
| <Type Name="std::ffi::c_str::CStr"> | |
| <DisplayString>{(char*) inner}</DisplayString> | |
| <Expand> | |
| <Synthetic Name="[chars]"> | |
| <DisplayString>{(char*) inner}</DisplayString> | |
| <Expand> | |
| <ArrayItems> | |
| <Size>strlen((char *) inner) + 1</Size> | |
| <ValuePointer>(char*)inner</ValuePointer> | |
| </ArrayItems> | |
| </Expand> | |
| </Synthetic> | |
| </Expand> | |
| </Type> | |
| <Type Name="std::ffi::os_str::OsString"> | |
| <DisplayString>{(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString> | |
| <Expand> | |
| <Synthetic Name="[chars]"> | |
| <DisplayString>{(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString> | |
| <Expand> | |
| <ArrayItems> | |
| <Size>inner.inner.bytes.len</Size> | |
| <ValuePointer>(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer</ValuePointer> | |
| </ArrayItems> | |
| </Expand> | |
| </Synthetic> | |
| </Expand> | |
| </Type> | |
| </AutoVisualizer> |