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