use std::error::Error;
use std::fmt::Debug;
use serde::{Deserialize, Serialize};
use crate::destination::MessageDestination;
use crate::message::Message;
use crate::message_router::RoutingInfo;
pub trait RoutedDestination {
fn get_id(&self) -> &str;
fn get_destination(&self) -> &dyn MessageDestination;
fn get_routing_info(&self) -> &RoutingInfo;
fn send(&self, message: &Message) -> Result<(), Box<dyn Error>> {
self.get_destination().send(message)
}
fn is_root(&self) -> bool {
self.get_routing_info().get_routing_behaviour() == &MessageRoutingBehaviour::Root
}
fn get_routing_type(&self) -> &MessageRoutingBehaviour {
&self.get_routing_info().get_routing_behaviour()
}
fn should_receive(&self, m: &Message) -> bool {
self.get_routing_info().applies_to(m)
}
}
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub enum MessageRoutingBehaviour {
Root,
Drain,
Additive
}
impl MessageRoutingBehaviour {
pub fn always_send_messages(&self) -> bool {
match &self {
MessageRoutingBehaviour::Root => true,
MessageRoutingBehaviour::Additive => true,
MessageRoutingBehaviour::Drain => false,
}
}
pub fn always_receives_errors(&self) -> bool {
match &self {
MessageRoutingBehaviour::Root => true,
MessageRoutingBehaviour::Drain => false,
MessageRoutingBehaviour::Additive => false,
}
}
}
impl Default for MessageRoutingBehaviour {
fn default() -> Self {
MessageRoutingBehaviour::Additive
}
}
#[derive(Debug)]
pub struct RoutedDestinationBase {
id: String,
destination: Box<dyn MessageDestination>,
routing_info: RoutingInfo,
}
impl RoutedDestinationBase {
pub fn new(id: String, destination: Box<dyn MessageDestination>, routing_info: RoutingInfo) -> Self {
Self {
id,
destination,
routing_info,
}
}
pub fn create<M: MessageDestination + 'static>(id: String, destination: M, routing_info: RoutingInfo) -> Self {
Self {
id,
destination: Box::new(destination),
routing_info,
}
}
}
impl RoutedDestination for RoutedDestinationBase {
fn get_id(&self) -> &str {
&self.id
}
fn get_destination(&self) -> &dyn MessageDestination {
&*self.destination
}
fn get_routing_info(&self) -> &RoutingInfo {
&self.routing_info
}
}
#[cfg(test)]
mod test {
use std::sync::mpsc;
use std::sync::mpsc::TryRecvError;
use super::*;
use crate::destination::kinds::rust_receiver::RustReceiverDestination;
use crate::message::{Level, MessageDetail};
use crate::message::author::Author;
#[test]
pub fn test_send_message() {
let (send, recv) = mpsc::channel();
let dest = RoutedDestinationBase::create("test".to_owned(), RustReceiverDestination::create(send), RoutingInfo::root());
let message = Message::new(Level::Info,
None, MessageDetail::Raw("hello".to_owned()),
None, Author::parse("test".to_owned()), 104892);
assert_eq!(recv.try_recv(), Err(TryRecvError::Empty), "Should be empty before we send a message");
dest.send(&message).expect("Should not fail to send message");
assert_eq!(recv.try_recv(), Ok(message));
}
}