cl-structures: Give the StringArena a new home.

This commit is contained in:
John 2024-04-24 19:52:56 -05:00
parent 40ec9b30e4
commit d4432cda7a
3 changed files with 51 additions and 50 deletions

View File

@ -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 }
}
}

View File

@ -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};

View 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 }
}
}