use anymore::AnyDebug;
use alloc::boxed::Box;
use core::fmt::Debug;
#[derive(Default, Debug)]
pub enum MessageResult<Action> {
Action(Action),
RequestRebuild,
#[default]
Nop,
Stale,
}
impl<A> MessageResult<A> {
pub fn map<B>(self, f: impl FnOnce(A) -> B) -> MessageResult<B> {
match self {
Self::Action(a) => MessageResult::Action(f(a)),
Self::RequestRebuild => MessageResult::RequestRebuild,
Self::Stale => MessageResult::Stale,
Self::Nop => MessageResult::Nop,
}
}
}
#[derive(Debug)]
pub struct DynMessage(pub Box<dyn AnyDebug>);
impl DynMessage {
pub fn new(x: impl AnyDebug) -> Self {
Self(Box::new(x))
}
pub fn downcast<T: AnyDebug>(self) -> Result<Box<T>, Self> {
self.0.downcast().map_err(Self)
}
pub fn is<T: AnyDebug>(&self) -> bool {
self.0.is::<T>()
}
}
#[derive(Debug)]
pub struct SendMessage(pub Box<dyn AnyDebug + Send>);
impl From<SendMessage> for DynMessage {
fn from(value: SendMessage) -> Self {
Self(value.0)
}
}
impl SendMessage {
pub fn new(x: impl AnyDebug + Send) -> Self {
Self(Box::new(x))
}
pub fn downcast<T: AnyDebug>(self) -> Result<Box<T>, Self> {
self.0.downcast().map_err(Self)
}
pub fn is<T: AnyDebug + Send>(&self) -> bool {
self.0.is::<T>()
}
}
#[cfg(test)]
mod tests {
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use core::fmt::Debug;
use crate::DynMessage;
struct MyMessage(String);
impl Debug for MyMessage {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_fmt(format_args!("A present message: {:?}", self.0))
}
}
#[derive(Debug)]
struct NotMyMessage;
#[test]
fn message_downcast() {
let message = DynMessage::new(MyMessage("test".to_string()));
let result: Box<MyMessage> = message.downcast().unwrap();
assert_eq!(&result.0, "test");
}
#[test]
fn message_downcast_wrong_type() {
let message = DynMessage::new(MyMessage("test".to_string()));
let message = message.downcast::<NotMyMessage>().unwrap_err();
let result: Box<MyMessage> = message.downcast().unwrap();
assert_eq!(&result.0, "test");
}
#[test]
fn message_debug() {
let message = DynMessage::new(MyMessage("".to_string()));
let debug_result = format!("{message:?}");
assert!(debug_result.contains("A present message"));
}
}