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 , table_rev: BTreeMap , 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); } }