tari_utilities/
message_format.rs1use alloc::{string::String, vec::Vec};
26
27use serde::{de::DeserializeOwned, Deserialize, Serialize};
28use snafu::prelude::*;
29
30#[derive(Debug, Snafu)]
32#[allow(missing_docs)]
33pub enum MessageFormatError {
34 #[snafu(display("An error occurred serialising an object into binary"))]
35 BinarySerializeError {},
36 #[snafu(display("An error occurred deserialising binary data into an object"))]
37 BinaryDeserializeError {},
38 #[snafu(display("An error occurred de-/serialising an object from/into JSON"))]
39 JSONError {},
40 #[snafu(display("An error occurred deserialising an object from Base64"))]
41 Base64DeserializeError {},
42}
43
44pub trait MessageFormat: Sized {
46 fn to_binary(&self) -> Result<Vec<u8>, MessageFormatError>;
48 fn to_json(&self) -> Result<String, MessageFormatError>;
50 fn to_base64(&self) -> Result<String, MessageFormatError>;
52
53 fn from_binary(msg: &[u8]) -> Result<Self, MessageFormatError>;
55 fn from_json(msg: &str) -> Result<Self, MessageFormatError>;
57 fn from_base64(msg: &str) -> Result<Self, MessageFormatError>;
59}
60
61impl<T> MessageFormat for T
62where T: DeserializeOwned + Serialize
63{
64 fn to_binary(&self) -> Result<Vec<u8>, MessageFormatError> {
65 bincode::serialize(self).map_err(|_| MessageFormatError::BinarySerializeError {})
66 }
67
68 fn to_json(&self) -> Result<String, MessageFormatError> {
69 serde_json::to_string(self).map_err(|_| MessageFormatError::JSONError {})
70 }
71
72 fn to_base64(&self) -> Result<String, MessageFormatError> {
73 let val = self.to_binary()?;
74 Ok(base64::encode(val))
75 }
76
77 fn from_binary(msg: &[u8]) -> Result<Self, MessageFormatError> {
78 bincode::deserialize(msg).map_err(|_| MessageFormatError::BinaryDeserializeError {})
79 }
80
81 fn from_json(msg: &str) -> Result<Self, MessageFormatError> {
82 let mut de = serde_json::Deserializer::from_reader(msg.as_bytes());
83 Deserialize::deserialize(&mut de).map_err(|_| MessageFormatError::JSONError {})
84 }
85
86 fn from_base64(msg: &str) -> Result<Self, MessageFormatError> {
87 let buf = base64::decode(msg).map_err(|_| MessageFormatError::Base64DeserializeError {})?;
88 Self::from_binary(&buf)
89 }
90}
91
92#[cfg(test)]
93mod test {
94 use alloc::{boxed::Box, string::ToString};
95
96 use serde::{Deserialize, Serialize};
97
98 use super::*;
99
100 #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
101 struct TestMessage {
102 key: String,
103 value: u64,
104 sub_message: Option<Box<TestMessage>>,
105 }
106
107 impl TestMessage {
108 pub fn new(key: &str, value: u64) -> TestMessage {
109 TestMessage {
110 key: key.to_string(),
111 value,
112 sub_message: None,
113 }
114 }
115
116 pub fn set_sub_message(&mut self, msg: TestMessage) {
117 self.sub_message = Some(Box::new(msg));
118 }
119 }
120
121 #[test]
122 fn binary_simple() {
123 let val = TestMessage::new("twenty", 20);
124 let msg = val.to_binary().unwrap();
125 assert_eq!(
126 msg,
127 b"\x06\x00\x00\x00\x00\x00\x00\x00\x74\x77\x65\x6e\x74\x79\x14\x00\x00\x00\x00\x00\x00\x00\x00"
128 );
129 let val2 = TestMessage::from_binary(&msg).unwrap();
130 assert_eq!(val, val2);
131 }
132
133 #[test]
134 fn base64_simple() {
135 let val = TestMessage::new("twenty", 20);
136 let msg = val.to_base64().unwrap();
137 assert_eq!(msg, "BgAAAAAAAAB0d2VudHkUAAAAAAAAAAA=");
138 let val2 = TestMessage::from_base64(&msg).unwrap();
139 assert_eq!(val, val2);
140 }
141
142 #[test]
143 fn json_simple() {
144 let val = TestMessage::new("twenty", 20);
145 let msg = val.to_json().unwrap();
146 assert_eq!(msg, "{\"key\":\"twenty\",\"value\":20,\"sub_message\":null}");
147 let val2 = TestMessage::from_json(&msg).unwrap();
148 assert_eq!(val, val2);
149 }
150
151 #[test]
152 fn nested_message() {
153 let inner = TestMessage::new("today", 100);
154 let mut val = TestMessage::new("tomorrow", 50);
155 val.set_sub_message(inner);
156
157 let msg_json = val.to_json().unwrap();
158 assert_eq!(
159 msg_json,
160 "{\"key\":\"tomorrow\",\"value\":50,\"sub_message\":{\"key\":\"today\",\"value\":100,\"sub_message\":\
161 null}}"
162 );
163
164 let msg_base64 = val.to_base64().unwrap();
165 assert_eq!(
166 msg_base64,
167 "CAAAAAAAAAB0b21vcnJvdzIAAAAAAAAAAQUAAAAAAAAAdG9kYXlkAAAAAAAAAAA="
168 );
169
170 let msg_bin = val.to_binary().unwrap();
171 assert_eq!(
172 msg_bin,
173 b"\x08\x00\x00\x00\x00\x00\x00\x00\x74\x6f\x6d\x6f\x72\x72\x6f\x77\x32\x00\x00\x00\x00\x00\x00\x00\x01\x05\x00\x00\x00\x00\x00\x00\x00\x74\x6f\x64\x61\x79\x64\x00\x00\x00\x00\x00\x00\x00\x00".to_vec()
174 );
175
176 let val2 = TestMessage::from_json(&msg_json).unwrap();
177 assert_eq!(val, val2);
178
179 let val2 = TestMessage::from_base64(&msg_base64).unwrap();
180 assert_eq!(val, val2);
181
182 let val2 = TestMessage::from_binary(&msg_bin).unwrap();
183 assert_eq!(val, val2);
184 }
185
186 #[test]
187 fn fail_json() {
188 let err = TestMessage::from_json("{\"key\":5}").unwrap_err();
189 assert!(matches!(err, MessageFormatError::JSONError {}));
190 }
191
192 #[test]
193 fn fail_base64() {
194 let err = TestMessage::from_base64("aaaaa$aaaaa").unwrap_err();
195 assert!(matches!(err, MessageFormatError::Base64DeserializeError {}));
196
197 let err = TestMessage::from_base64("j6h0b21vcnJvdzKTpXRvZGF5ZMA=").unwrap_err();
198 assert!(matches!(err, MessageFormatError::BinaryDeserializeError {}));
199 }
200
201 #[test]
202 fn fail_binary() {
203 let err = TestMessage::from_binary(b"").unwrap_err();
204 assert!(matches!(err, MessageFormatError::BinaryDeserializeError {}));
205 }
206}