xpx_chain_sdk/models/message/
message.rs

1/*
2 * Copyright 2018 ProximaX Limited. All rights reserved.
3 * Use of this source code is governed by the Apache 2.0
4 * license that can be found in the LICENSE file.
5 */
6
7use std::fmt;
8
9use crate::helpers::is_hex;
10
11use super::{MessageType, PlainMessage};
12
13/// An abstract message trait that serves as the base of all message types.
14///
15#[typetag::serde]
16pub trait Message: Sync + Send + erased_serde::Serialize
17where
18    Self: fmt::Debug,
19{
20    fn message_type(&self) -> MessageType;
21
22    fn box_clone(&self) -> Box<dyn Message>;
23
24    fn payload(&self) -> String;
25
26    fn payload_to_vec(&self) -> Vec<u8> {
27        let mut buf = Vec::new();
28        let payload_str = self.payload();
29        if is_hex(&payload_str) {
30            buf.extend(hex::decode(&payload_str).unwrap())
31        } else {
32            buf.extend(payload_str.as_bytes())
33        };
34
35        buf
36    }
37
38    fn to_vec(&self) -> Vec<u8> {
39        if self.payload().is_empty() {
40            return vec![];
41        };
42        let mut buf = Vec::new();
43        buf.extend(self.message_type().to_bytes().to_vec());
44        buf.extend(self.payload_to_vec());
45        buf
46    }
47
48    fn to_dto(&self) -> String {
49        use MessageType::*;
50
51        if self.payload().is_empty() {
52            return String::new();
53        };
54        match self.message_type() {
55            PlainMessageType | SecureMessageType => {
56                let dto = hex::encode((self.message_type().value() as u8).to_be_bytes());
57                dto + &hex::encode(&self.payload_to_vec())
58            }
59            _ => String::new(),
60        }
61            .to_uppercase()
62    }
63}
64
65impl dyn Message {
66    pub fn empty_message() -> PlainMessage {
67        PlainMessage::default()
68    }
69}
70
71impl Clone for Box<dyn Message + 'static> {
72    fn clone(&self) -> Box<dyn Message + 'static> {
73        self.box_clone()
74    }
75}
76
77impl<'a> PartialEq for &'a dyn Message {
78    fn eq(&self, other: &Self) -> bool {
79        self.to_vec() == other.to_vec()
80    }
81}
82
83impl<'a> PartialEq for Box<dyn Message + 'static> {
84    fn eq(&self, other: &Self) -> bool {
85        self.as_ref() == other.as_ref()
86    }
87}
88
89impl fmt::Display for dyn Message {
90    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91        write!(f, "{}", serde_json::to_string_pretty(&self).unwrap_or_default())
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use crate::helpers::utf8_to_hex;
98    use crate::message::{Message, MessageType, PlainMessage, SecureMessage};
99
100    #[test]
101    fn test_should_create_an_plain_message_dto_struct() {
102        let message = PlainMessage::create("test");
103        assert_eq!(message.to_dto(), format!("00{}", utf8_to_hex("test").to_uppercase()));
104    }
105
106    #[test]
107    fn test_should_create_an_encrypted_message_dto_struct() {
108        let message =
109            SecureMessage { r#type: MessageType::SecureMessageType, payload: "test".to_string() };
110        assert_eq!(message.to_dto(), format!("01{}", utf8_to_hex("test").to_uppercase()));
111    }
112}