use std::any::{type_name, Any}; use frunk::{prelude::HList, HCons, HNil}; use crate::Aero; /// Bound on the types that can be used as an aerosol resource. pub trait Resource: Any + Send + Sync + Clone {} impl Resource for T {} /// A compile-time list of resource types which are statically guaranteed to be present. pub trait ResourceList: HList + Any + Send + Sync + Clone { /// Test at runtmie whether every resource in this list is present in the given Aero instance. fn test(aero: &Aero) -> bool; } impl ResourceList for HNil { fn test(_aero: &Aero) -> bool { true } } impl ResourceList for HCons { fn test(aero: &Aero) -> bool { aero.has::() && T::test(aero) } } pub(crate) fn missing_resource() -> ! { panic!("Resource `{}` does not exist", type_name::()) } pub(crate) fn unwrap_resource(opt: Option) -> T { if let Some(value) = opt { value } else { missing_resource::() } } pub(crate) fn unwrap_constructed(res: Result>) -> U { match res { Ok(x) => x, Err(e) => panic!("Failed to construct `{}`: {}", type_name::(), e.into()), } } pub(crate) fn unwrap_constructed_hlist(res: Result>) -> U { match res { Ok(x) => x, Err(e) => panic!( "Failed to construct one of `{}`: {}", type_name::(), e.into() ), } } pub(crate) fn duplicate_resource() -> ! { panic!( "Duplicate resource: attempted to add a second `{}`", type_name::() ) } pub(crate) fn cyclic_resource() -> ! { panic!( "Cycle detected when constructing resource `{}`", type_name::() ) }