1use std::fmt;
2
3use serde::de::DeserializeOwned;
4use serde_json::Value;
5
6use crate::error::Error;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Message {
13 json: String,
14}
15
16impl Message {
17 pub fn from_json(json: impl Into<String>) -> Message {
20 Message { json: json.into() }
21 }
22
23 pub fn decode<T: DeserializeOwned>(&self) -> Result<T, Error> {
25 Ok(serde_json::from_str(&self.json)?)
26 }
27
28 pub fn to_value(&self) -> Result<Value, Error> {
30 self.decode()
31 }
32
33 pub fn as_str(&self) -> &str {
35 &self.json
36 }
37}
38
39impl fmt::Display for Message {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 f.write_str(&self.json)
42 }
43}
44
45#[cfg(test)]
46#[allow(
47 clippy::unwrap_used,
48 clippy::expect_used,
49 reason = "a test that can't have what it asked for has nothing left to assert"
50)]
51mod tests {
52 use serde::Deserialize;
53
54 use super::*;
55
56 #[derive(Debug, PartialEq, Deserialize)]
57 struct Said {
58 body: String,
59 }
60
61 #[test]
62 fn a_message_decodes_into_the_callers_type() {
63 let message = Message::from_json(r#"{"body":"Hello!"}"#);
64
65 let said: Said = message.decode().unwrap();
66
67 assert_eq!("Hello!", said.body);
68 assert_eq!(r#"{"body":"Hello!"}"#, message.to_string());
69 assert!(matches!(
70 Message::from_json("not json").decode::<Said>(),
71 Err(Error::Json(_))
72 ));
73 }
74}