Re-order internals

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2025-11-05 10:59:42 +01:00
parent db03733d3c
commit bf3e65a6e2
3 changed files with 169 additions and 152 deletions

View 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()
)
})
})
}
}
}

View file

@ -3,154 +3,18 @@
#[macro_use]
mod macros;
pub mod address;
pub mod message;
use std::any::Any;
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 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 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);
pub use message::InternalMessage;
pub use message::Message;
pub use message::MessageBundle;
#[derive(Debug, Clone, Copy)]
pub struct BundleChain {
@ -159,7 +23,7 @@ pub struct BundleChain {
}
#[derive(Debug, Clone, Copy)]
pub enum BundleOp {
enum BundleOp {
Add(TypeId),
Remove(TypeId),
Chain(&'static BundleChain),
@ -167,6 +31,13 @@ pub enum BundleOp {
}
impl BundleChain {
pub const fn empty() -> BundleChain {
BundleChain {
op: BundleOp::None,
next: None,
}
}
pub const fn of<M: Message>() -> BundleChain {
BundleChain {
op: BundleOp::Add(TypeId::of::<M>()),
@ -234,13 +105,6 @@ impl BundleChain {
next: Some(ids),
}
}
pub const fn empty() -> BundleChain {
BundleChain {
op: BundleOp::None,
next: None,
}
}
}
pub trait IsContainedInBundle<MB> {

View 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);