1use serde::{Serialize, de::DeserializeOwned};
7
8use crate::error::WsError;
9
10pub trait Codec: Sized {
29 fn encode(&self) -> String
37 where
38 Self: Serialize,
39 {
40 serde_json::to_string(self).unwrap_or_default()
41 }
42
43 fn encode_result(&self) -> Result<String, WsError>
45 where
46 Self: Serialize,
47 {
48 serde_json::to_string(self).map_err(|_| WsError::InvalidMessage)
49 }
50
51 fn decode(s: &str) -> Result<Self, WsError>
53 where
54 Self: DeserializeOwned,
55 {
56 serde_json::from_str(s).map_err(|_| WsError::InvalidMessage)
57 }
58}
59
60impl<T> Codec for T where T: Serialize + DeserializeOwned {}
62
63pub struct JsonCodec;
66
67impl JsonCodec {
68 pub fn encode<T: Serialize>(value: &T) -> Result<String, WsError> {
70 serde_json::to_string(value).map_err(|_| WsError::InvalidMessage)
71 }
72
73 pub fn decode<T: DeserializeOwned>(s: &str) -> Result<T, WsError> {
75 serde_json::from_str(s).map_err(|_| WsError::InvalidMessage)
76 }
77
78 pub fn encode_pretty<T: Serialize>(value: &T) -> Result<String, WsError> {
80 serde_json::to_string_pretty(value).map_err(|_| WsError::InvalidMessage)
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use serde::{Deserialize, Serialize};
88
89 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
90 struct Payload {
91 id: u32,
92 msg: String,
93 }
94
95 #[test]
96 fn codec_roundtrip_trait() {
97 let p = Payload {
98 id: 42,
99 msg: "hello".into(),
100 };
101 let s = p.encode();
102 let d = Payload::decode(&s).unwrap();
103 assert_eq!(p, d);
104 }
105
106 #[test]
107 fn codec_roundtrip_result() {
108 let p = Payload {
109 id: 1,
110 msg: "world".into(),
111 };
112 let s = p.encode_result().unwrap();
113 let d = Payload::decode(&s).unwrap();
114 assert_eq!(p, d);
115 }
116
117 #[test]
118 fn codec_invalid_decode() {
119 let err = Payload::decode("not json").unwrap_err();
120 assert_eq!(err, WsError::InvalidMessage);
121 }
122
123 #[test]
124 fn json_codec_helpers() {
125 let p = Payload {
126 id: 7,
127 msg: "test".into(),
128 };
129 let s = JsonCodec::encode(&p).unwrap();
130 let d: Payload = JsonCodec::decode(&s).unwrap();
131 assert_eq!(p, d);
132
133 let pretty = JsonCodec::encode_pretty(&p).unwrap();
134 assert!(pretty.contains('\n'));
135 }
136
137 #[test]
138 fn encode_vec() {
139 let v = vec![1, 2, 3];
140 let s = v.encode();
141 let d: Vec<i32> = Vec::decode(&s).unwrap();
142 assert_eq!(v, d);
143 }
144}