42 lines
1.2 KiB
Rust
42 lines
1.2 KiB
Rust
|
use std::collections::BTreeMap;
|
||
|
|
||
|
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, Gc<'gc, A>>>);
|
||
|
|
||
|
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 + 'static,
|
||
|
{
|
||
|
let intern_map: &'gc InternMapSingleton<'gc, A> =
|
||
|
ctx.singleton::<Rootable!['gcb => InternMapSingleton<'gcb, A>]>();
|
||
|
let gc_id = intern_map
|
||
|
.0
|
||
|
.borrow_mut(&ctx)
|
||
|
.entry(input.clone())
|
||
|
.or_insert_with(|| Gc::new(&ctx, input.clone()))
|
||
|
.clone();
|
||
|
UserData::<'gc>::new::<Rootable!['gcb => Gc<'gcb, A>]>(&ctx, gc_id).into_value(ctx)
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
}
|