47 lines
1.3 KiB
Rust
47 lines
1.3 KiB
Rust
use std::{collections::BTreeMap, fmt::Debug};
|
|
|
|
use gc_arena::{lock::GcRefLock, Collect, Gc, Rootable};
|
|
use piccolo::{Context, IntoValue, Singleton, UserData, Value};
|
|
|
|
#[derive(Collect)]
|
|
#[collect(no_drop)]
|
|
struct InternMapSingleton<'gc, A>(GcRefLock<'gc, BTreeMap<A, Value<'gc>>>);
|
|
|
|
impl<'gc, A> Singleton<'gc> for InternMapSingleton<'gc, A>
|
|
where
|
|
A: Collect,
|
|
{
|
|
fn create(ctx: Context<'gc>) -> Self {
|
|
InternMapSingleton(Gc::new(&ctx, Default::default()))
|
|
}
|
|
}
|
|
|
|
pub fn intern_id<'gc, A>(ctx: Context<'gc>, input: A) -> Value<'gc>
|
|
where
|
|
A: Collect + Ord + Clone + Debug + 'static,
|
|
{
|
|
let intern_map: &'gc InternMapSingleton<'gc, A> =
|
|
ctx.singleton::<Rootable!['gcb => InternMapSingleton<'gcb, A>]>();
|
|
intern_map
|
|
.0
|
|
.borrow_mut(&ctx)
|
|
.entry(input.clone())
|
|
.or_insert_with(|| {
|
|
UserData::<'gc>::new::<Rootable!['gcb => Gc<'gcb, A>]>(
|
|
&ctx,
|
|
Gc::new(&ctx, input.clone()),
|
|
)
|
|
.into_value(ctx)
|
|
})
|
|
.clone()
|
|
}
|
|
|
|
pub fn unintern_id<'gc, A>(ctx: Context<'gc>, input: &A)
|
|
where
|
|
A: Collect + Ord + Clone + 'static,
|
|
{
|
|
let intern_map: &InternMapSingleton<'gc, A> =
|
|
ctx.singleton::<Rootable!['gcb => InternMapSingleton<'gcb, A>]>();
|
|
intern_map.0.borrow_mut(&ctx).remove(input);
|
|
}
|