Phase 2: InternedStr and Interner types (infrastructure)

This commit is contained in:
Glint Dev
2026-07-21 20:35:56 +03:00
parent f3ea96258c
commit a46c9bc9e7
2 changed files with 72 additions and 2 deletions

View File

@@ -2,9 +2,78 @@ use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;
use super::style::{ComputedStyle, StyleSheet};
use compact_str::CompactString;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct InternedStr(u32);
impl InternedStr {
pub const fn from_raw(id: u32) -> Self {
Self(id)
}
pub fn raw(&self) -> u32 {
self.0
}
}
impl InternedStr {
pub fn eq_str(&self, other: &str) -> bool {
with_interner(|interner| interner.lookup(*self) == other)
}
}
#[derive(Debug, Clone)]
pub struct Interner {
strings: Vec<String>,
map: HashMap<String, u32>,
next_id: u32,
}
impl Interner {
pub fn new() -> Self {
Self {
strings: Vec::new(),
map: HashMap::new(),
next_id: 0,
}
}
pub fn intern(&mut self, s: &str) -> InternedStr {
if let Some(&id) = self.map.get(s) {
return InternedStr(id);
}
let id = self.next_id;
self.next_id += 1;
self.strings.push(s.to_string());
self.map.insert(s.to_string(), id);
InternedStr(id)
}
pub fn lookup(&self, id: InternedStr) -> &str {
&self.strings[id.0 as usize]
}
pub fn intern_or_none(&mut self, s: Option<&str>) -> Option<InternedStr> {
s.map(|s| self.intern(s))
}
}
use std::cell::RefCell;
thread_local! {
static GLOBAL_INTERNER: RefCell<Interner> = RefCell::new(Interner::new());
}
pub fn with_interner<F, R>(f: F) -> R
where
F: FnOnce(&mut Interner) -> R,
{
GLOBAL_INTERNER.with(|i| f(&mut *i.borrow_mut()))
}
#[derive(Clone, Debug)]
pub enum Value {
Str(CompactString),
@@ -128,6 +197,7 @@ pub struct Document<'a> {
pub variables: HashMap<String, Value>,
pub rhei_scripts: Vec<String>,
pub stylesheet: StyleSheet,
pub interner: Interner,
}
#[derive(Debug)]