forked from Orchid/orchid
53 lines
1.8 KiB
Rust
53 lines
1.8 KiB
Rust
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<C: SystemCard> {
|
|
pub(crate) _card: C,
|
|
pub(crate) id: api::SysId,
|
|
}
|
|
impl<C: SystemCard> SystemHandle<C> {
|
|
pub(crate) fn new(id: api::SysId) -> Self { Self { _card: C::default(), id } }
|
|
pub fn id(&self) -> api::SysId { self.id }
|
|
}
|
|
impl<C: SystemCard> Clone for SystemHandle<C> {
|
|
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<dyn DynSystemCard>;
|
|
}
|
|
|
|
impl<C: SystemCard> DynSystemHandle for SystemHandle<C> {
|
|
fn id(&self) -> api::SysId { self.id }
|
|
fn get_card(&self) -> Box<dyn DynSystemCard> { 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<Sys: SystemCard, Req: Request + Into<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>() {
|
|
sys_id()
|
|
} else {
|
|
(cted.deps().find(|s| s.get_card().type_id() == TypeId::of::<Sys>()))
|
|
.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()
|
|
}
|