worldwideportal/src/id_intern.rs

42 lines
1.2 KiB
Rust
Raw Normal View History

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