cl-structures: Give the StringArena a new home.
This commit is contained in:
		@@ -1,54 +1,7 @@
 | 
			
		||||
//! Simple, long-lived string buffer
 | 
			
		||||
 | 
			
		||||
use std::marker::PhantomData;
 | 
			
		||||
use symbol::Symbol;
 | 
			
		||||
//! Simple arena-like allocation
 | 
			
		||||
 | 
			
		||||
pub mod global_intern;
 | 
			
		||||
pub mod intern;
 | 
			
		||||
pub mod string_arena;
 | 
			
		||||
pub mod symbol;
 | 
			
		||||
 | 
			
		||||
/// Compactly stores a set of immutable strings, producing a [Symbol] for each one
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct StringArena<T: Symbol> {
 | 
			
		||||
    ends: Vec<usize>,
 | 
			
		||||
    buf: String,
 | 
			
		||||
    _t: PhantomData<fn(T)>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Symbol> StringArena<T> {
 | 
			
		||||
    pub fn new() -> Self {
 | 
			
		||||
        Default::default()
 | 
			
		||||
    }
 | 
			
		||||
    /// # May panic
 | 
			
		||||
    /// Panics if Symbol::from_usize would panic
 | 
			
		||||
    fn next_key(&self) -> T {
 | 
			
		||||
        Symbol::from_usize(self.ends.len())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_span(&self, key: T) -> Option<(usize, usize)> {
 | 
			
		||||
        let key = key.into_usize();
 | 
			
		||||
        Some((*self.ends.get(key - 1)?, *self.ends.get(key)?))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get(&self, key: T) -> Option<&str> {
 | 
			
		||||
        let (start, end) = self.get_span(key)?;
 | 
			
		||||
        // Safety: start and end offsets were created by push_string
 | 
			
		||||
        Some(unsafe { self.buf.get_unchecked(start..end) })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn push_string(&mut self, s: &str) -> T {
 | 
			
		||||
        if self.ends.is_empty() {
 | 
			
		||||
            self.ends.push(self.buf.len())
 | 
			
		||||
        }
 | 
			
		||||
        let key = self.next_key();
 | 
			
		||||
        self.buf.push_str(s);
 | 
			
		||||
        self.ends.push(self.buf.len());
 | 
			
		||||
        key
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Symbol> Default for StringArena<T> {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self { ends: Default::default(), buf: Default::default(), _t: PhantomData }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
//! A string interner with deduplication
 | 
			
		||||
 | 
			
		||||
use super::{symbol::Symbol, StringArena};
 | 
			
		||||
use super::{string_arena::StringArena, symbol::Symbol};
 | 
			
		||||
use hashbrown::hash_table::HashTable;
 | 
			
		||||
use std::hash::{BuildHasher, RandomState};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								compiler/cl-structures/src/arena/string_arena.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								compiler/cl-structures/src/arena/string_arena.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
//! Compactly stores a set of immutable strings, producing a [Symbol] for each one
 | 
			
		||||
use super::symbol::Symbol;
 | 
			
		||||
use std::marker::PhantomData;
 | 
			
		||||
/// Compactly stores a set of immutable strings, producing a [Symbol] for each one
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct StringArena<T: Symbol> {
 | 
			
		||||
    ends: Vec<usize>,
 | 
			
		||||
    buf: String,
 | 
			
		||||
    _t: PhantomData<fn(T)>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Symbol> StringArena<T> {
 | 
			
		||||
    pub fn new() -> Self {
 | 
			
		||||
        Default::default()
 | 
			
		||||
    }
 | 
			
		||||
    /// # May panic
 | 
			
		||||
    /// Panics if Symbol::from_usize would panic
 | 
			
		||||
    fn next_key(&self) -> T {
 | 
			
		||||
        Symbol::from_usize(self.ends.len())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_span(&self, key: T) -> Option<(usize, usize)> {
 | 
			
		||||
        let key = key.into_usize();
 | 
			
		||||
        Some((*self.ends.get(key - 1)?, *self.ends.get(key)?))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get(&self, key: T) -> Option<&str> {
 | 
			
		||||
        let (start, end) = self.get_span(key)?;
 | 
			
		||||
        // Safety: start and end offsets were created by push_string
 | 
			
		||||
        Some(unsafe { self.buf.get_unchecked(start..end) })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn push_string(&mut self, s: &str) -> T {
 | 
			
		||||
        if self.ends.is_empty() {
 | 
			
		||||
            self.ends.push(self.buf.len())
 | 
			
		||||
        }
 | 
			
		||||
        let key = self.next_key();
 | 
			
		||||
        self.buf.push_str(s);
 | 
			
		||||
        self.ends.push(self.buf.len());
 | 
			
		||||
        key
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Symbol> Default for StringArena<T> {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self { ends: Default::default(), buf: Default::default(), _t: PhantomData }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user