1use rustc_hash::FxHashMap as HashMap;
11
12use crate::object::NameId;
13
14pub struct NameTable {
16 names: Vec<Vec<u8>>,
17 lookup: HashMap<Vec<u8>, NameId>,
18}
19
20impl NameTable {
21 pub fn new() -> Self {
22 Self {
23 names: Vec::new(),
24 lookup: HashMap::default(),
25 }
26 }
27
28 pub fn intern(&mut self, name: &[u8]) -> NameId {
30 if let Some(&id) = self.lookup.get(name) {
31 return id;
32 }
33 let id = NameId(self.names.len() as u32);
34 self.names.push(name.to_vec());
35 self.lookup.insert(name.to_vec(), id);
36 id
37 }
38
39 pub fn get_bytes(&self, id: NameId) -> &[u8] {
41 &self.names[id.0 as usize]
42 }
43
44 pub fn find(&self, name: &[u8]) -> Option<NameId> {
46 self.lookup.get(name).copied()
47 }
48}
49
50impl Default for NameTable {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_intern_and_lookup() {
62 let mut table = NameTable::new();
63 let id1 = table.intern(b"add");
64 let id2 = table.intern(b"sub");
65 let id3 = table.intern(b"add"); assert_eq!(id1, id3);
68 assert_ne!(id1, id2);
69 assert_eq!(table.get_bytes(id1), b"add");
70 assert_eq!(table.get_bytes(id2), b"sub");
71 }
72
73 #[test]
74 fn test_find() {
75 let mut table = NameTable::new();
76 assert_eq!(table.find(b"foo"), None);
77 let id = table.intern(b"foo");
78 assert_eq!(table.find(b"foo"), Some(id));
79 }
80}