code_moniker_workspace/snapshot/inventory/
facets.rs1use std::sync::Arc;
2
3use rustc_hash::FxHashMap;
4
5use super::{InventorySegment, InventorySymbol, SourceId, SymbolOrdinal, SymbolSet};
6
7#[derive(Clone, Debug, Default, Eq, PartialEq)]
11pub struct SymbolInventoryFacets {
12 by_identity: FxHashMap<Arc<str>, SymbolSet>,
13 by_name: FxHashMap<Arc<str>, SymbolSet>,
14 by_kind: FxHashMap<Arc<str>, SymbolSet>,
15 by_shape: FxHashMap<Arc<str>, SymbolSet>,
16 by_visibility: FxHashMap<Arc<str>, SymbolSet>,
17 by_language: FxHashMap<Arc<str>, SymbolSet>,
18 by_source: FxHashMap<SourceId, SymbolSet>,
19 by_source_path: FxHashMap<Arc<str>, SymbolSet>,
20 by_source_root: FxHashMap<usize, SymbolSet>,
21 by_srcset: FxHashMap<Arc<str>, SymbolSet>,
22 by_segment: FxHashMap<InventorySegment, SymbolSet>,
23}
24
25impl SymbolInventoryFacets {
26 pub(super) fn estimated_heap_bytes(&self) -> usize {
27 string_postings_bytes(&self.by_identity)
28 + string_postings_bytes(&self.by_name)
29 + string_postings_bytes(&self.by_kind)
30 + string_postings_bytes(&self.by_shape)
31 + string_postings_bytes(&self.by_visibility)
32 + string_postings_bytes(&self.by_language)
33 + postings_bytes(&self.by_source)
34 + string_postings_bytes(&self.by_source_path)
35 + postings_bytes(&self.by_source_root)
36 + string_postings_bytes(&self.by_srcset)
37 + postings_bytes(&self.by_segment)
38 }
39
40 pub fn symbols_by_identity(&self, identity: &str) -> Option<&SymbolSet> {
41 self.by_identity.get(identity)
42 }
43
44 pub fn symbols_by_name(&self, name: &str) -> Option<&SymbolSet> {
45 self.by_name.get(name)
46 }
47
48 pub fn name_postings(&self) -> impl Iterator<Item = (&str, &SymbolSet)> {
49 posting_values(&self.by_name)
50 }
51
52 pub fn symbols_by_kind(&self, kind: &str) -> Option<&SymbolSet> {
53 self.by_kind.get(kind)
54 }
55
56 pub fn kind_postings(&self) -> impl Iterator<Item = (&str, &SymbolSet)> {
57 posting_values(&self.by_kind)
58 }
59
60 pub fn symbols_by_shape(&self, shape: &str) -> Option<&SymbolSet> {
61 self.by_shape.get(shape)
62 }
63
64 pub fn shape_postings(&self) -> impl Iterator<Item = (&str, &SymbolSet)> {
65 posting_values(&self.by_shape)
66 }
67
68 pub fn symbols_by_visibility(&self, visibility: &str) -> Option<&SymbolSet> {
69 self.by_visibility.get(visibility)
70 }
71
72 pub fn visibility_postings(&self) -> impl Iterator<Item = (&str, &SymbolSet)> {
73 posting_values(&self.by_visibility)
74 }
75
76 pub fn symbols_by_language(&self, language: &str) -> Option<&SymbolSet> {
77 self.by_language.get(language)
78 }
79
80 pub fn language_postings(&self) -> impl Iterator<Item = (&str, &SymbolSet)> {
81 posting_values(&self.by_language)
82 }
83
84 pub fn symbols_by_source(&self, source: SourceId) -> Option<&SymbolSet> {
85 self.by_source.get(&source)
86 }
87
88 pub fn symbols_by_source_path(&self, path: &str) -> Option<&SymbolSet> {
89 self.by_source_path.get(path)
90 }
91
92 pub fn source_path_postings(&self) -> impl Iterator<Item = (&str, &SymbolSet)> {
93 posting_values(&self.by_source_path)
94 }
95
96 pub fn symbols_by_source_root(&self, root: usize) -> Option<&SymbolSet> {
97 self.by_source_root.get(&root)
98 }
99
100 pub fn symbols_by_srcset(&self, srcset: &str) -> Option<&SymbolSet> {
101 self.by_srcset.get(srcset)
102 }
103
104 pub fn srcset_postings(&self) -> impl Iterator<Item = (&str, &SymbolSet)> {
105 posting_values(&self.by_srcset)
106 }
107
108 pub fn symbols_by_segment(&self, kind: &str, name: &str) -> Option<&SymbolSet> {
109 self.by_segment.get(&InventorySegment {
110 kind: Arc::from(kind),
111 name: Arc::from(name),
112 })
113 }
114
115 pub fn segment_postings(&self) -> impl Iterator<Item = (&InventorySegment, &SymbolSet)> {
116 self.by_segment.iter()
117 }
118}
119
120fn postings_bytes<K>(postings: &FxHashMap<K, SymbolSet>) -> usize {
121 postings.capacity() * (std::mem::size_of::<K>() + std::mem::size_of::<SymbolSet>())
122 + postings
123 .values()
124 .map(SymbolSet::estimated_heap_bytes)
125 .sum::<usize>()
126}
127
128fn string_postings_bytes(postings: &FxHashMap<Arc<str>, SymbolSet>) -> usize {
129 postings_bytes(postings)
130}
131
132pub(super) fn insert_facets(
133 facets: &mut SymbolInventoryFacets,
134 record: &InventorySymbol,
135 ordinal: SymbolOrdinal,
136) {
137 insert_posting(
138 &mut facets.by_identity,
139 Arc::clone(&record.identity),
140 ordinal,
141 );
142 insert_posting(&mut facets.by_name, Arc::clone(&record.name), ordinal);
143 insert_posting(&mut facets.by_kind, Arc::clone(&record.kind), ordinal);
144 insert_posting(&mut facets.by_shape, Arc::clone(&record.shape), ordinal);
145 insert_posting(
146 &mut facets.by_visibility,
147 Arc::clone(&record.visibility),
148 ordinal,
149 );
150 insert_posting(
151 &mut facets.by_language,
152 Arc::clone(&record.language),
153 ordinal,
154 );
155 insert_posting(&mut facets.by_source, record.source, ordinal);
156 insert_posting(
157 &mut facets.by_source_path,
158 Arc::clone(&record.source_path),
159 ordinal,
160 );
161 insert_posting(&mut facets.by_source_root, record.source_root, ordinal);
162 insert_posting(&mut facets.by_srcset, Arc::clone(&record.srcset), ordinal);
163 for segment in record.segments.iter() {
164 insert_posting(&mut facets.by_segment, segment.clone(), ordinal);
165 }
166}
167
168pub(super) fn remove_facets(
169 facets: &mut SymbolInventoryFacets,
170 record: &InventorySymbol,
171 ordinal: SymbolOrdinal,
172) {
173 remove_posting(&mut facets.by_identity, &record.identity, ordinal);
174 remove_posting(&mut facets.by_name, &record.name, ordinal);
175 remove_posting(&mut facets.by_kind, &record.kind, ordinal);
176 remove_posting(&mut facets.by_shape, &record.shape, ordinal);
177 remove_posting(&mut facets.by_visibility, &record.visibility, ordinal);
178 remove_posting(&mut facets.by_language, &record.language, ordinal);
179 remove_posting(&mut facets.by_source, &record.source, ordinal);
180 remove_posting(&mut facets.by_source_path, &record.source_path, ordinal);
181 remove_posting(&mut facets.by_source_root, &record.source_root, ordinal);
182 remove_posting(&mut facets.by_srcset, &record.srcset, ordinal);
183 for segment in record.segments.iter() {
184 remove_posting(&mut facets.by_segment, segment, ordinal);
185 }
186}
187
188fn posting_values(
189 index: &FxHashMap<Arc<str>, SymbolSet>,
190) -> impl Iterator<Item = (&str, &SymbolSet)> {
191 index
192 .iter()
193 .map(|(value, symbols)| (value.as_ref(), symbols))
194}
195
196fn insert_posting<K: Eq + std::hash::Hash>(
197 index: &mut FxHashMap<K, SymbolSet>,
198 key: K,
199 ordinal: SymbolOrdinal,
200) {
201 index.entry(key).or_default().insert(ordinal);
202}
203
204fn remove_posting<K: Eq + std::hash::Hash>(
205 index: &mut FxHashMap<K, SymbolSet>,
206 key: &K,
207 ordinal: SymbolOrdinal,
208) {
209 if let Some(symbols) = index.get_mut(key) {
210 symbols.remove(ordinal);
211 if symbols.is_empty() {
212 index.remove(key);
213 }
214 }
215}