worldwideportal/src/id_intern.rs

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);
}