use iris_core::{WidgetId, util::HashMap}; 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 { 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 key = Key { ty, i: *count, id }; self.map.insert(key, Box::new(data)); *count += 1; WeakState { key, _pd: PhantomData, } } pub fn remove(&mut self, state: WeakState) { self.map.remove(&state.key); } 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) } }