use iris_core::{ WidgetId, util::{HashMap, HashSet}, }; use std::{ any::{Any, TypeId}, marker::PhantomData, }; #[derive(Clone, Copy, PartialEq, Eq, Hash)] struct Key { id: WidgetId, ty: TypeId, i: usize, } #[derive(Default)] pub struct WidgetState { widgets: HashMap>, counts: HashMap<(WidgetId, TypeId), usize>, map: HashMap>, } impl WidgetState { pub fn new() -> Self { Self::default() } pub fn add(&mut self, id: WidgetId, data: T) -> WeakState { let ty = TypeId::of::(); let count = self.counts.entry((id, ty)).or_default(); let i = *count; let key = Key { ty, i, id }; self.map.insert(key, Box::new(data)); self.widgets.entry(id).or_default().insert((ty, i)); *count += 1; WeakState { key, _pd: PhantomData, } } pub fn remove(&mut self, id: WidgetId) { for &(ty, i) in self.widgets.get(&id).into_iter().flatten() { self.map.remove(&Key { id, ty, i }); } } pub fn get(&self, state: WeakState) -> &T { self.map.get(&state.key).unwrap().downcast_ref().unwrap() } pub fn get_mut(&mut self, state: WeakState) -> &mut T { self.map .get_mut(&state.key) .unwrap() .downcast_mut() .unwrap() } } #[derive(Clone, Copy)] pub struct WeakState { key: Key, _pd: PhantomData, } pub trait HasWidgetState { fn widget_state(&self) -> &WidgetState; fn widget_state_mut(&mut self) -> &mut WidgetState; } impl<'a, T: 'static> FnOnce<(&'a mut WidgetState,)> for WeakState { type Output = &'a mut T; extern "rust-call" fn call_once(self, (state,): (&'a mut WidgetState,)) -> Self::Output { state.get_mut(self) } }