#[cfg(all(
feature = "hash-collections",
not(feature = "prefer-btree-collections")
))]
mod detail {
use super::{GetOrInternWithHint, Sym};
use crate::hash;
use string_interner::{backend::BufferBackend, StringInterner, Symbol};
pub type StringInternerImpl = StringInterner<BufferBackend<Sym>, hash::RandomState>;
impl GetOrInternWithHint for StringInternerImpl {
#[inline]
fn get_or_intern_with_hint<T>(&mut self, string: T, _hint: super::InternHint) -> Sym
where
T: AsRef<str>,
{
self.get_or_intern(string)
}
}
impl Symbol for Sym {
#[inline]
fn try_from_usize(index: usize) -> Option<Self> {
let Ok(value) = u32::try_from(index) else {
return None;
};
Some(Self::from_u32(value))
}
#[inline]
fn to_usize(self) -> usize {
self.into_u32() as usize
}
}
}
#[cfg(any(
not(feature = "hash-collections"),
feature = "prefer-btree-collections"
))]
mod detail;
#[derive(Debug, Copy, Clone)]
pub enum InternHint {
None,
LikelyExists,
LikelyNew,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Sym(u32);
impl Sym {
pub fn from_u32(value: u32) -> Self {
Self(value)
}
pub fn from_usize(value: usize) -> Self {
u32::try_from(value).map_or_else(|_| panic!("out of bounds symbol index: {value}"), Self)
}
pub fn into_u32(self) -> u32 {
self.0
}
pub fn into_usize(self) -> usize {
self.0 as usize
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StringInterner {
inner: detail::StringInternerImpl,
}
impl Default for StringInterner {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl StringInterner {
#[inline]
pub fn new() -> Self {
Self {
inner: detail::StringInternerImpl::new(),
}
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline]
pub fn get<T>(&self, string: T) -> Option<Sym>
where
T: AsRef<str>,
{
self.inner.get(string)
}
#[inline]
pub fn get_or_intern<T>(&mut self, string: T) -> Sym
where
T: AsRef<str>,
{
self.inner.get_or_intern_with_hint(string, InternHint::None)
}
#[inline]
pub fn get_or_intern_with_hint<T>(&mut self, string: T, hint: InternHint) -> Sym
where
T: AsRef<str>,
{
self.inner.get_or_intern_with_hint(string, hint)
}
#[inline]
pub fn resolve(&self, symbol: Sym) -> Option<&str> {
self.inner.resolve(symbol)
}
}
trait GetOrInternWithHint {
fn get_or_intern_with_hint<T>(&mut self, string: T, hint: InternHint) -> Sym
where
T: AsRef<str>;
}