lunar_wave/lunar_wave_vm/src/string_interner.rs

57 lines
1.2 KiB
Rust

use std::collections::BTreeMap;
use crate::value::Value;
#[derive (Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct InternedString (i64);
#[derive (Debug, Default)]
pub struct Interner {
table_fwd: BTreeMap <String, i64>,
table_rev: BTreeMap <i64, String>,
counter: i64,
}
impl Interner {
pub fn get (&self, s: InternedString) -> &str {
self.table_rev.get (&s.0).unwrap ()
}
pub fn intern (&mut self, s: &str) -> InternedString {
match self.table_fwd.get (s) {
Some (x) => InternedString (*x),
None => {
self.counter += 1;
if self.counter == i64::MAX {
panic! ("Out of IDs");
}
self.table_fwd.insert (s.to_string (), self.counter);
self.table_rev.insert (self.counter, s.to_string ());
InternedString (self.counter)
}
}
}
pub fn to_value (&mut self, s: &str) -> Value {
Value::from (self.intern (s))
}
}
#[cfg (test)]
mod tests {
use super::*;
#[test]
fn test () {
let mut interner = Interner::default ();
assert_eq! (interner.intern ("x").0, 1);
assert_eq! (interner.intern ("x").0, 1);
assert_eq! (interner.intern ("y").0, 2);
assert_eq! (interner.intern ("z").0, 3);
assert_eq! (interner.intern ("y").0, 2);
assert_eq! (interner.intern ("asdf").0, 4);
}
}