Adapt internals
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
d1ad9bac7f
commit
db03733d3c
3 changed files with 239 additions and 55 deletions
|
|
@ -1,8 +1,13 @@
|
|||
#![feature(const_cmp)]
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
use std::any::Any;
|
||||
use std::any::TypeId;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
|
||||
pub use anyhow;
|
||||
|
||||
|
|
@ -10,14 +15,6 @@ pub trait Message: Send + Any {
|
|||
type Reply: Send + Any;
|
||||
}
|
||||
|
||||
pub trait MessageIdentifier {
|
||||
const IDENT: BundleChain;
|
||||
}
|
||||
|
||||
impl<M: Message> MessageIdentifier for M {
|
||||
const IDENT: BundleChain = BundleChain::of::<M>();
|
||||
}
|
||||
|
||||
pub struct InternalMessage {
|
||||
value: Box<dyn std::any::Any>,
|
||||
name: &'static str,
|
||||
|
|
@ -58,6 +55,46 @@ pub trait Address<MB> {
|
|||
fn send<M: Message>(&mut self, message: M) -> impl Future<Output = anyhow::Result<M::Reply>>;
|
||||
}
|
||||
|
||||
pub struct BoxedAddress<MB> {
|
||||
addr: Box<dyn Any>,
|
||||
#[allow(clippy::type_complexity)]
|
||||
send: for<'a> fn(
|
||||
&'a mut dyn Any,
|
||||
InternalMessage,
|
||||
) -> Pin<Box<dyn Future<Output = anyhow::Result<InternalMessage>> + 'a>>,
|
||||
_pd: PhantomData<fn(MB)>,
|
||||
}
|
||||
|
||||
impl<MB> BoxedAddress<MB> {
|
||||
pub fn new<IMH>(addr: IMH) -> Self
|
||||
where
|
||||
IMH: InternalMessageHandler<HandledMessages = MB> + 'static,
|
||||
{
|
||||
BoxedAddress {
|
||||
addr: Box::new(addr),
|
||||
send: |addr, msg| {
|
||||
let addr: &mut IMH = addr.downcast_mut().unwrap();
|
||||
|
||||
Box::pin(addr.handle_message(msg))
|
||||
},
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<MB> InternalMessageHandler for BoxedAddress<MB>
|
||||
where
|
||||
MB: MessageBundle,
|
||||
{
|
||||
type HandledMessages = MB;
|
||||
fn handle_message(
|
||||
&mut self,
|
||||
msg: InternalMessage,
|
||||
) -> impl Future<Output = anyhow::Result<InternalMessage>> {
|
||||
(self.send)(self.addr.as_mut(), msg)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InternalMessageHandler {
|
||||
type HandledMessages: MessageBundle;
|
||||
fn handle_message(
|
||||
|
|
@ -93,22 +130,27 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub trait MessageReceiver {}
|
||||
|
||||
pub trait MessageBundle {
|
||||
const IDS: BundleChain;
|
||||
const CHAIN: BundleChain;
|
||||
}
|
||||
|
||||
impl MessageBundle for () {
|
||||
const IDS: BundleChain = BundleChain {
|
||||
next: None,
|
||||
op: BundleOp::Remove(TypeId::of::<()>()),
|
||||
const CHAIN: BundleChain = BundleChain::empty();
|
||||
}
|
||||
|
||||
macro_rules! impl_message_bundles {
|
||||
( [ $($ty:ident),* ] , $last:ident ) => {
|
||||
impl<$($ty,)* $last> MessageBundle for ($($ty,)* $last,)
|
||||
where
|
||||
$( $ty: Message, )*
|
||||
$last: Message,
|
||||
{
|
||||
const CHAIN: BundleChain = <($($ty,)*) as MessageBundle>::CHAIN.with::<$last>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<M: Message> MessageBundle for (M,) {
|
||||
const IDS: BundleChain = BundleChain::of::<M>();
|
||||
}
|
||||
all_the_tuples_special_first!(impl_message_bundles);
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct BundleChain {
|
||||
|
|
@ -121,6 +163,7 @@ pub enum BundleOp {
|
|||
Add(TypeId),
|
||||
Remove(TypeId),
|
||||
Chain(&'static BundleChain),
|
||||
None,
|
||||
}
|
||||
|
||||
impl BundleChain {
|
||||
|
|
@ -135,6 +178,40 @@ impl BundleChain {
|
|||
check_is_contained(self, id)
|
||||
}
|
||||
|
||||
pub const fn is_subset_of(&self, ids: &BundleChain) -> bool {
|
||||
let mut current = self;
|
||||
|
||||
loop {
|
||||
match current.op {
|
||||
BundleOp::Add(type_id) => {
|
||||
if !ids.contains(type_id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BundleOp::Remove(..) => (),
|
||||
BundleOp::Chain(bundle_chain) => {
|
||||
let chain_result = bundle_chain.is_subset_of(ids);
|
||||
let own_result = if let Some(bc) = self.next {
|
||||
bc.is_subset_of(ids)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
return chain_result && own_result;
|
||||
}
|
||||
BundleOp::None => (),
|
||||
}
|
||||
|
||||
if let Some(next) = current.next {
|
||||
current = next;
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub const fn with<M: Message>(&'static self) -> BundleChain {
|
||||
let to_add = TypeId::of::<M>();
|
||||
BundleChain {
|
||||
|
|
@ -157,24 +234,13 @@ impl BundleChain {
|
|||
next: Some(ids),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> MessageBundle for (A, B)
|
||||
where
|
||||
A: Message,
|
||||
B: Message,
|
||||
{
|
||||
const IDS: BundleChain = BundleChain::of::<A>().with::<B>();
|
||||
}
|
||||
|
||||
impl<A, B, C, D> MessageBundle for (A, B, C, D)
|
||||
where
|
||||
A: Message,
|
||||
B: Message,
|
||||
C: Message,
|
||||
D: Message,
|
||||
{
|
||||
const IDS: BundleChain = BundleChain::of::<A>().with::<B>().with::<C>().with::<D>();
|
||||
pub const fn empty() -> BundleChain {
|
||||
BundleChain {
|
||||
op: BundleOp::None,
|
||||
next: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IsContainedInBundle<MB> {
|
||||
|
|
@ -186,7 +252,7 @@ where
|
|||
M: Message,
|
||||
MB: MessageBundle,
|
||||
{
|
||||
const IS_CONTAINED: bool = check_is_contained(&MB::IDS, TypeId::of::<M>());
|
||||
const IS_CONTAINED: bool = check_is_contained(&MB::CHAIN, TypeId::of::<M>());
|
||||
}
|
||||
|
||||
const fn check_is_contained(ids: &BundleChain, id: TypeId) -> bool {
|
||||
|
|
@ -206,6 +272,7 @@ const fn check_is_contained(ids: &BundleChain, id: TypeId) -> bool {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
BundleOp::None => (),
|
||||
}
|
||||
|
||||
if let Some(next) = ids.next {
|
||||
|
|
@ -269,6 +336,16 @@ mod tests {
|
|||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_subset() {
|
||||
const CHAIN: BundleChain = BundleChain::of::<Foo>().join(&BundleChain::of::<Bar>());
|
||||
const SUB: BundleChain = BundleChain::of::<Foo>().with::<Bar>();
|
||||
|
||||
assert!(SUB.is_subset_of(&CHAIN));
|
||||
|
||||
assert!(!BundleChain::of::<Zap>().is_subset_of(&CHAIN));
|
||||
}
|
||||
|
||||
#[apply(test!)]
|
||||
async fn check_sending_messages() {
|
||||
struct Sender;
|
||||
|
|
|
|||
21
crates/tytix-core/src/macros.rs
Normal file
21
crates/tytix-core/src/macros.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#[rustfmt::skip]
|
||||
macro_rules! all_the_tuples_special_first {
|
||||
($name:ident) => {
|
||||
$name!([], M1);
|
||||
$name!([M1], M2);
|
||||
$name!([M1, M2], M3);
|
||||
$name!([M1, M2, M3], M4);
|
||||
$name!([M1, M2, M3, M4], M5);
|
||||
$name!([M1, M2, M3, M4, M5], M6);
|
||||
$name!([M1, M2, M3, M4, M5, M6], M7);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7], M8);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8], M9);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8, M9], M10);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8, M9, M10], M11);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11], M12);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12], M13);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13], M14);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14], M15);
|
||||
$name!([M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15], M16);
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue