use std::any::TypeId; use orchid_api_traits::{Decode, Encode, Request}; use crate::system::{dyn_cted, sys_id}; use crate::{DynSystemCard, SystemCard, api, request}; /// A reference to an instance of an alternate system, passed to /// [crate::SystemCtor::inst] for dependencies. It can be accepted by functions /// that call [sys_req] to prove a dependency relationship. #[derive(Debug)] pub struct SystemHandle { pub(crate) _card: C, pub(crate) id: api::SysId, } impl SystemHandle { pub(crate) fn new(id: api::SysId) -> Self { Self { _card: C::default(), id } } pub fn id(&self) -> api::SysId { self.id } } impl Clone for SystemHandle { fn clone(&self) -> Self { Self::new(self.id) } } /// Type-erased system handle, not used for anything at the moment pub trait DynSystemHandle { fn id(&self) -> api::SysId; fn get_card(&self) -> Box; } impl DynSystemHandle for SystemHandle { fn id(&self) -> api::SysId { self.id } fn get_card(&self) -> Box { Box::new(C::default()) } } /// Make a global request to a system that supports this request type. The /// target system must either be the system in which this function is called, or /// one of its direct dependencies. pub async fn sys_req>(req: Req) -> Req::Response { let mut msg = Vec::new(); req.into().encode_vec(&mut msg); let cted = dyn_cted(); let own_inst = cted.inst(); let owner = if own_inst.card().type_id() == TypeId::of::() { sys_id() } else { (cted.deps().find(|s| s.get_card().type_id() == TypeId::of::())) .expect("System not in dependency array yet we have a handle somehow") .id() }; let reply = request(api::SysFwd(owner, msg)).await; Req::Response::decode(std::pin::pin!(&reply[..])).await.unwrap() }