1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use std::any::{Any, TypeId};

#[derive(Debug)]
pub enum MessageError {
    WrongType(TypeId),
}

/// A message box is a container for wrapping a message.
#[derive(Debug)]
pub struct MessageBox {
    message: Box<dyn Any>,
    message_type: TypeId,
}

impl MessageBox {
    pub fn new<M: Any>(message: M) -> Self {
        MessageBox {
            message: Box::new(message),
            message_type: TypeId::of::<M>(),
        }
    }

    pub fn is_type<M: Any>(&self) -> bool {
        self.message_type == TypeId::of::<M>()
    }

    pub fn message_type(&self) -> TypeId {
        self.message_type
    }

    pub fn downcast<M: Any>(self) -> Result<M, MessageError> {
        if self.message_type == TypeId::of::<M>() {
            return Ok(*self.message.downcast::<M>().unwrap());
        }

        Err(MessageError::WrongType(TypeId::of::<M>()))
    }

    pub fn downcast_ref<M: Any>(&self) -> Result<&M, MessageError> {
        if self.message_type == TypeId::of::<M>() {
            return Ok(&*self.message.downcast_ref::<M>().unwrap());
        }

        Err(MessageError::WrongType(TypeId::of::<M>()))
    }
}

/// Used to sent a simple string message over the message channel.
#[derive(Default, Clone)]
pub struct StringMessage(pub String);

impl From<&str> for StringMessage {
    fn from(s: &str) -> Self {
        StringMessage(s.to_string())
    }
}

impl From<String> for StringMessage {
    fn from(s: String) -> Self {
        StringMessage(s)
    }
}

impl Into<MessageBox> for StringMessage {
    fn into(self) -> MessageBox {
        MessageBox::new(self)
    }
}