Skip to main content

stet_core/
name.rs

1// stet - A PostScript Interpreter
2// Copyright (c) 2026 Scott Bowman
3// SPDX-License-Identifier: Apache-2.0 OR MIT
4
5//! Name interning table.
6//!
7//! Maps byte sequences to `NameId` values. Names persist forever
8//! (not subject to save/restore or GC).
9
10use rustc_hash::FxHashMap as HashMap;
11
12use crate::object::NameId;
13
14/// Interning table: maps byte sequences to unique `NameId` values.
15pub 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    /// Get or create a `NameId` for the given byte sequence.
29    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    /// Get the byte sequence for a `NameId`.
40    pub fn get_bytes(&self, id: NameId) -> &[u8] {
41        &self.names[id.0 as usize]
42    }
43
44    /// Look up a name without creating it.
45    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"); // same as id1
66
67        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}