Re-order internals
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
db03733d3c
commit
bf3e65a6e2
3 changed files with 169 additions and 152 deletions
87
crates/tytix-core/src/address.rs
Normal file
87
crates/tytix-core/src/address.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
use std::any::Any;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
use crate::InternalMessage;
|
||||||
|
use crate::IsContainedInBundle;
|
||||||
|
use crate::Message;
|
||||||
|
use crate::MessageBundle;
|
||||||
|
|
||||||
|
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(
|
||||||
|
&mut self,
|
||||||
|
msg: InternalMessage,
|
||||||
|
) -> impl Future<Output = anyhow::Result<InternalMessage>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IMH> Address<IMH::HandledMessages> for IMH
|
||||||
|
where
|
||||||
|
IMH: InternalMessageHandler,
|
||||||
|
{
|
||||||
|
fn send<M: Message>(&mut self, message: M) -> impl Future<Output = anyhow::Result<M::Reply>> {
|
||||||
|
const {
|
||||||
|
let true = <M as IsContainedInBundle<IMH::HandledMessages>>::IS_CONTAINED else {
|
||||||
|
panic!("Message is not contained in MessageBundle",);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = self.handle_message(InternalMessage::new(message));
|
||||||
|
|
||||||
|
async {
|
||||||
|
message.await.and_then(|msg| {
|
||||||
|
msg.into_inner::<M::Reply>().map_err(|e| {
|
||||||
|
anyhow::anyhow!(
|
||||||
|
"Expected a {}, but got a {}",
|
||||||
|
std::any::type_name::<M::Reply>(),
|
||||||
|
e.type_name()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,154 +3,18 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
pub mod address;
|
||||||
|
pub mod message;
|
||||||
|
|
||||||
use std::any::Any;
|
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::pin::Pin;
|
|
||||||
|
|
||||||
|
pub use address::Address;
|
||||||
|
pub use address::BoxedAddress;
|
||||||
|
pub use address::InternalMessageHandler;
|
||||||
pub use anyhow;
|
pub use anyhow;
|
||||||
|
pub use message::InternalMessage;
|
||||||
pub trait Message: Send + Any {
|
pub use message::Message;
|
||||||
type Reply: Send + Any;
|
pub use message::MessageBundle;
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InternalMessage {
|
|
||||||
value: Box<dyn std::any::Any>,
|
|
||||||
name: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InternalMessage {
|
|
||||||
pub fn new<M: Any>(message: M) -> InternalMessage {
|
|
||||||
InternalMessage {
|
|
||||||
value: Box::new(message),
|
|
||||||
name: std::any::type_name::<M>(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_inner<M: Any>(self) -> Result<M, InternalMessage> {
|
|
||||||
self.value
|
|
||||||
.downcast()
|
|
||||||
.map(|v| *v)
|
|
||||||
.map_err(|value| InternalMessage {
|
|
||||||
value,
|
|
||||||
name: self.name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_ref<M: Any>(&self) -> Option<&M> {
|
|
||||||
self.value.downcast_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_name(&self) -> &'static str {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_id(&self) -> TypeId {
|
|
||||||
self.value.as_ref().type_id()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
&mut self,
|
|
||||||
msg: InternalMessage,
|
|
||||||
) -> impl Future<Output = anyhow::Result<InternalMessage>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<IMH> Address<IMH::HandledMessages> for IMH
|
|
||||||
where
|
|
||||||
IMH: InternalMessageHandler,
|
|
||||||
{
|
|
||||||
fn send<M: Message>(&mut self, message: M) -> impl Future<Output = anyhow::Result<M::Reply>> {
|
|
||||||
const {
|
|
||||||
let true = <M as IsContainedInBundle<IMH::HandledMessages>>::IS_CONTAINED else {
|
|
||||||
panic!("Message is not contained in MessageBundle",);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let message = self.handle_message(InternalMessage::new(message));
|
|
||||||
|
|
||||||
async {
|
|
||||||
message.await.and_then(|msg| {
|
|
||||||
msg.into_inner::<M::Reply>().map_err(|e| {
|
|
||||||
anyhow::anyhow!(
|
|
||||||
"Expected a {}, but got a {}",
|
|
||||||
std::any::type_name::<M::Reply>(),
|
|
||||||
e.type_name()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait MessageBundle {
|
|
||||||
const CHAIN: BundleChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MessageBundle for () {
|
|
||||||
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>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
all_the_tuples_special_first!(impl_message_bundles);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct BundleChain {
|
pub struct BundleChain {
|
||||||
|
|
@ -159,7 +23,7 @@ pub struct BundleChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum BundleOp {
|
enum BundleOp {
|
||||||
Add(TypeId),
|
Add(TypeId),
|
||||||
Remove(TypeId),
|
Remove(TypeId),
|
||||||
Chain(&'static BundleChain),
|
Chain(&'static BundleChain),
|
||||||
|
|
@ -167,6 +31,13 @@ pub enum BundleOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BundleChain {
|
impl BundleChain {
|
||||||
|
pub const fn empty() -> BundleChain {
|
||||||
|
BundleChain {
|
||||||
|
op: BundleOp::None,
|
||||||
|
next: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn of<M: Message>() -> BundleChain {
|
pub const fn of<M: Message>() -> BundleChain {
|
||||||
BundleChain {
|
BundleChain {
|
||||||
op: BundleOp::Add(TypeId::of::<M>()),
|
op: BundleOp::Add(TypeId::of::<M>()),
|
||||||
|
|
@ -234,13 +105,6 @@ impl BundleChain {
|
||||||
next: Some(ids),
|
next: Some(ids),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn empty() -> BundleChain {
|
|
||||||
BundleChain {
|
|
||||||
op: BundleOp::None,
|
|
||||||
next: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IsContainedInBundle<MB> {
|
pub trait IsContainedInBundle<MB> {
|
||||||
|
|
|
||||||
66
crates/tytix-core/src/message.rs
Normal file
66
crates/tytix-core/src/message.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
use std::any::Any;
|
||||||
|
use std::any::TypeId;
|
||||||
|
|
||||||
|
use crate::BundleChain;
|
||||||
|
|
||||||
|
pub trait Message: Send + Any {
|
||||||
|
type Reply: Send + Any;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InternalMessage {
|
||||||
|
value: Box<dyn std::any::Any>,
|
||||||
|
name: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InternalMessage {
|
||||||
|
pub fn new<M: Any>(message: M) -> InternalMessage {
|
||||||
|
InternalMessage {
|
||||||
|
value: Box::new(message),
|
||||||
|
name: std::any::type_name::<M>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_inner<M: Any>(self) -> Result<M, InternalMessage> {
|
||||||
|
self.value
|
||||||
|
.downcast()
|
||||||
|
.map(|v| *v)
|
||||||
|
.map_err(|value| InternalMessage {
|
||||||
|
value,
|
||||||
|
name: self.name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ref<M: Any>(&self) -> Option<&M> {
|
||||||
|
self.value.downcast_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_name(&self) -> &'static str {
|
||||||
|
self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_id(&self) -> TypeId {
|
||||||
|
self.value.as_ref().type_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MessageBundle {
|
||||||
|
const CHAIN: BundleChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageBundle for () {
|
||||||
|
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>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
all_the_tuples_special_first!(impl_message_bundles);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue