code_moniker_workspace/snapshot/inventory/
catalog.rs1use rustc_hash::FxHashMap;
2
3use super::{SymbolId, SymbolOrdinal, SymbolSet};
4
5#[derive(Clone, Debug, Default, Eq, PartialEq)]
9pub struct SymbolOrdinalCatalog {
10 next_ordinal: u32,
11 ids: FxHashMap<SymbolOrdinal, SymbolId>,
12 ordinals_by_id: FxHashMap<SymbolId, SymbolOrdinal>,
13}
14
15impl SymbolOrdinalCatalog {
16 pub(super) fn estimated_heap_bytes(&self) -> usize {
17 self.ids.capacity()
18 * (std::mem::size_of::<SymbolOrdinal>() + std::mem::size_of::<SymbolId>())
19 + self.ordinals_by_id.capacity()
20 * (std::mem::size_of::<SymbolId>() + std::mem::size_of::<SymbolOrdinal>())
21 }
22
23 pub fn push(&mut self, id: SymbolId) -> SymbolOrdinal {
24 if let Some(ordinal) = self.ordinals_by_id.get(&id).copied() {
25 return ordinal;
26 }
27 let ordinal = SymbolOrdinal::from_index(self.next_ordinal as usize);
28 assert!(
29 self.next_ordinal < u32::MAX,
30 "symbol ordinal space exhausted"
31 );
32 self.next_ordinal += 1;
33 self.bind_id(ordinal, id);
34 ordinal
35 }
36
37 pub fn retire(&mut self, ordinal: SymbolOrdinal) {
38 self.unbind_id(ordinal);
39 }
40
41 pub(super) fn bind_id(&mut self, ordinal: SymbolOrdinal, id: SymbolId) {
42 if let Some(previous) = self.ids.insert(ordinal, id) {
43 self.ordinals_by_id.remove(&previous);
44 }
45 if let Some(previous_ordinal) = self.ordinals_by_id.insert(id, ordinal)
46 && previous_ordinal != ordinal
47 {
48 self.ids.remove(&previous_ordinal);
49 }
50 }
51
52 pub fn unbind_id(&mut self, ordinal: SymbolOrdinal) {
53 if let Some(previous_id) = self.ids.remove(&ordinal)
54 && self.ordinals_by_id.get(&previous_id) == Some(&ordinal)
55 {
56 self.ordinals_by_id.remove(&previous_id);
57 }
58 }
59
60 pub fn len(&self) -> usize {
61 self.ordinals_by_id.len()
62 }
63
64 pub fn is_empty(&self) -> bool {
65 self.len() == 0
66 }
67
68 pub fn storage_len(&self) -> usize {
69 self.ids.len()
70 }
71
72 pub fn ordinal(&self, id: &SymbolId) -> Option<SymbolOrdinal> {
73 self.ordinals_by_id.get(id).copied()
74 }
75
76 pub fn ids(&self, symbols: &SymbolSet) -> Vec<SymbolId> {
77 symbols
78 .iter()
79 .filter_map(|symbol| self.id(symbol).copied())
80 .collect()
81 }
82
83 pub fn id(&self, ordinal: SymbolOrdinal) -> Option<&SymbolId> {
84 self.ids.get(&ordinal)
85 }
86
87 pub fn active_ordinals(&self) -> impl Iterator<Item = (u32, SymbolId)> + '_ {
88 let mut ordinals = self
89 .ids
90 .iter()
91 .map(|(ordinal, id)| (ordinal.raw(), *id))
92 .collect::<Vec<_>>();
93 ordinals.sort_unstable_by_key(|(ordinal, _)| *ordinal);
94 ordinals.into_iter()
95 }
96}