57 lines
1.2 KiB
Rust
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);
|
|
}
|
|
}
|