Phase 2: InternedStr and Interner types (infrastructure)
This commit is contained in:
@@ -8,7 +8,7 @@ pub mod types;
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
pub use rhei::RheiContext;
|
pub use rhei::RheiContext;
|
||||||
use style::StyleSheet as SS;
|
use style::StyleSheet as SS;
|
||||||
pub use types::{ComponentDef, Document, Element, InterpError};
|
pub use types::{ComponentDef, Document, Element, Interner, InterpError};
|
||||||
|
|
||||||
use compact_str::CompactString;
|
use compact_str::CompactString;
|
||||||
use opcodes::*;
|
use opcodes::*;
|
||||||
@@ -44,7 +44,7 @@ impl Interpreter {
|
|||||||
//let rhei_ctx = RheiContext::new(&rhei_scripts);
|
//let rhei_ctx = RheiContext::new(&rhei_scripts);
|
||||||
//rhei_ctx.initialize(&mut variables);
|
//rhei_ctx.initialize(&mut variables);
|
||||||
|
|
||||||
Ok(Document { roots, components, variables, rhei_scripts, stylesheet })
|
Ok(Document { roots, components, variables, rhei_scripts, stylesheet, interner: Interner::new() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block_elements<'a>(
|
fn parse_block_elements<'a>(
|
||||||
|
|||||||
@@ -2,9 +2,78 @@ use std::borrow::Cow;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
|
||||||
use super::style::{ComputedStyle, StyleSheet};
|
use super::style::{ComputedStyle, StyleSheet};
|
||||||
use compact_str::CompactString;
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Str(CompactString),
|
Str(CompactString),
|
||||||
@@ -128,6 +197,7 @@ pub struct Document<'a> {
|
|||||||
pub variables: HashMap<String, Value>,
|
pub variables: HashMap<String, Value>,
|
||||||
pub rhei_scripts: Vec<String>,
|
pub rhei_scripts: Vec<String>,
|
||||||
pub stylesheet: StyleSheet,
|
pub stylesheet: StyleSheet,
|
||||||
|
pub interner: Interner,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
Reference in New Issue
Block a user