1use std::marker::PhantomData;
2
3use hashbrown::hash_map::RawEntryMut;
4
5use crate::pool::{SYMBOLS, Symbol, SymbolPtr, compute_hash};
6
7pub struct Pool<T: ?Sized> {
8 _phantom: PhantomData<T>,
9}
10
11impl Pool<[u8]> {
12 pub fn intern(value: &[u8]) -> Symbol<[u8]> {
13 let hash = compute_hash(value);
14
15 match SYMBOLS.lock().raw_entry_mut().from_key_hashed_nocheck(hash, value) {
16 RawEntryMut::Occupied(mut oe) => {
17 let (ptr, count) = oe.get_key_value_mut();
18
19 *count += 1;
20 Symbol::new(ptr.clone())
21 }
22 RawEntryMut::Vacant(ve) => {
23 let boxed = value.to_vec().into_boxed_slice();
24 let ptr = SymbolPtr::leaked(Box::leak(boxed));
25
26 ve.insert_hashed_nocheck(hash, ptr.clone(), 1);
27 Symbol::new(ptr)
28 }
29 }
30 }
31}
32
33impl Pool<str> {
34 pub fn intern(value: impl AsRef<str>) -> Symbol<str> {
35 let symbol = Pool::<[u8]>::intern(value.as_ref().as_bytes());
36 Symbol::new(symbol.into_ptr())
37 }
38}