use std::any::{Any, TypeId}; use std::fmt::Debug; use seq_macro::seq; use crate::lock::{Lock, WriteGuard}; use crate::system::{ComponentRefMut, Input as SystemInput}; use crate::type_name::TypeName; pub mod local; pub trait Component: SystemInput + Any + TypeName { fn drop_last(&self) -> bool; #[doc(hidden)] fn as_any_mut(&mut self) -> &mut dyn Any; #[doc(hidden)] fn as_any(&self) -> &dyn Any; } impl dyn Component { pub fn downcast_mut(&mut self) -> Option<&mut Real> { self.as_any_mut().downcast_mut() } pub fn downcast_ref(&self) -> Option<&Real> { self.as_any().downcast_ref() } pub fn is(&self) -> bool { self.as_any().is::() } } impl Debug for dyn Component { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.debug_struct("Component").finish_non_exhaustive() } } impl TypeName for Box { fn type_name(&self) -> &'static str { self.as_ref().type_name() } } /// A sequence of components. pub trait Sequence { type Refs<'component> where Self: 'component; fn into_vec(self) -> Vec>; fn type_ids() -> Vec; fn from_components<'component>( components: impl Iterator>>, ) -> Self::Refs<'component>; } macro_rules! inner { ($c: tt) => { seq!(I in 0..=$c { impl<#(Comp~I: Component,)*> Sequence for (#(Comp~I,)*) { type Refs<'component> = (#(ComponentRefMut<'component, Comp~I>,)*) where Self: 'component; fn into_vec(self) -> Vec> { Vec::from_iter([#(Box::new(self.I) as Box,)*]) } fn type_ids() -> Vec { vec![ #( TypeId::of::(), )* ] } fn from_components<'component>( components: impl Iterator>>, ) -> Self::Refs<'component> { #( let mut comp_~I: Option>> = None; )* for comp in components { let comp_ref = comp .write_nonblock() .expect("Failed to acquire read-write component lock"); #( if comp_ref.is::() { comp_~I = Some(comp_ref); continue; } )* } (#( ComponentRefMut::new( comp_~I.unwrap(), ), )*) } } }); }; } seq!(C in 0..=64 { inner!(C); });