use core::borrow::Borrow;
use std::hash::Hash;
pub mod string;
pub use string::StringBackend;
mod vec;
pub use vec::VecBackend;
pub trait DefaultBackendBuilder {
type Backend: Backend<Self>;
fn build_backend() -> Self::Backend;
}
pub type DefaultBackend<T> = <T as DefaultBackendBuilder>::Backend;
impl<T: Sized + Clone> DefaultBackendBuilder for T {
type Backend = VecBackend<T>;
fn build_backend() -> Self::Backend {
VecBackend::default()
}
}
impl DefaultBackendBuilder for str {
type Backend = StringBackend;
fn build_backend() -> Self::Backend {
StringBackend::default()
}
}
impl<T> DefaultBackendBuilder for [T] {
type Backend = VecBackend<T>;
fn build_backend() -> Self::Backend {
VecBackend::default()
}
}
pub trait BackendSymbol: Clone + Copy + Hash + Eq + PartialEq {}
impl<T> BackendSymbol for T where T: Clone + Copy + Hash + Eq + PartialEq {}
pub trait Backend<T: ?Sized> {
type Symbol: BackendSymbol;
fn intern<B>(&mut self, src: &B) -> Self::Symbol
where
T: Borrow<B>,
B: Internable<T, Self> + ?Sized,
{
src.intern_into(self)
}
fn get(&self, sym: Self::Symbol) -> Option<&T>;
unsafe fn get_unchecked(&self, sym: Self::Symbol) -> &T {
let val = self.get(sym);
debug_assert!(val.is_some());
unsafe { val.unwrap_unchecked() }
}
}
pub trait Internable<T, B>
where
T: Borrow<Self> + ?Sized,
B: Backend<T> + ?Sized,
{
fn intern_into(&self, b: &mut B) -> B::Symbol;
}