1use ruma_common::serde::from_raw_json_value;
2use serde::{Deserialize, Serialize, de, ser::SerializeStruct};
3use serde_json::value::RawValue as RawJsonValue;
4
5use super::{CustomPusherData, Pusher, PusherIds, PusherKind};
6
7#[derive(Debug, Deserialize)]
8struct PusherDeHelper {
9 #[serde(flatten)]
10 ids: PusherIds,
11 app_display_name: String,
12 device_display_name: String,
13 profile_tag: Option<String>,
14 lang: String,
15}
16
17impl<'de> Deserialize<'de> for Pusher {
18 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
19 where
20 D: de::Deserializer<'de>,
21 {
22 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
23
24 let PusherDeHelper { ids, app_display_name, device_display_name, profile_tag, lang } =
25 from_raw_json_value(&json)?;
26 let kind = from_raw_json_value(&json)?;
27
28 Ok(Self { ids, kind, app_display_name, device_display_name, profile_tag, lang })
29 }
30}
31
32impl Serialize for PusherKind {
33 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
34 where
35 S: serde::Serializer,
36 {
37 let mut st = serializer.serialize_struct("PusherAction", 3)?;
38
39 match self {
40 PusherKind::Http(data) => {
41 st.serialize_field("kind", &"http")?;
42 st.serialize_field("data", data)?;
43 }
44 PusherKind::Email(data) => {
45 st.serialize_field("kind", &"email")?;
46 st.serialize_field("data", data)?;
47 }
48 PusherKind::_Custom(custom) => {
49 st.serialize_field("kind", &custom.kind)?;
50 st.serialize_field("data", &custom.data)?;
51 }
52 }
53
54 st.end()
55 }
56}
57
58#[derive(Debug, Deserialize)]
59struct PusherKindDeHelper {
60 kind: String,
61 data: Box<RawJsonValue>,
62}
63
64impl<'de> Deserialize<'de> for PusherKind {
65 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
66 where
67 D: de::Deserializer<'de>,
68 {
69 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
70 let PusherKindDeHelper { kind, data } = from_raw_json_value(&json)?;
71
72 match kind.as_ref() {
73 "http" => from_raw_json_value(&data).map(Self::Http),
74 "email" => from_raw_json_value(&data).map(Self::Email),
75 _ => Ok(Self::_Custom(CustomPusherData { kind, data: from_raw_json_value(&data)? })),
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use ruma_common::{
83 canonical_json::assert_to_canonical_json_eq, push::HttpPusherData, serde::JsonObject,
84 };
85 use serde_json::{from_value as from_json_value, json};
86 use strass::assert_let;
87
88 use crate::push::{CustomPusherData, EmailPusherData, PusherKind};
89
90 #[test]
91 fn serialize_email() {
92 let mut data = EmailPusherData::new();
94 let action = PusherKind::Email(data.clone());
95
96 assert_to_canonical_json_eq!(
97 action,
98 json!({
99 "kind": "email",
100 "data": {},
101 })
102 );
103
104 data.data.insert("custom_key".to_owned(), "value".into());
106 let action = PusherKind::Email(data);
107
108 assert_to_canonical_json_eq!(
109 action,
110 json!({
111 "kind": "email",
112 "data": {
113 "custom_key": "value",
114 },
115 })
116 );
117 }
118
119 #[test]
120 fn serialize_http() {
121 let mut data = HttpPusherData::new("http://localhost".to_owned());
123 let action = PusherKind::Http(data.clone());
124
125 assert_to_canonical_json_eq!(
126 action,
127 json!({
128 "kind": "http",
129 "data": {
130 "url": "http://localhost",
131 },
132 })
133 );
134
135 data.data.insert("custom_key".to_owned(), "value".into());
137 let action = PusherKind::Http(data);
138
139 assert_to_canonical_json_eq!(
140 action,
141 json!({
142 "kind": "http",
143 "data": {
144 "url": "http://localhost",
145 "custom_key": "value",
146 },
147 })
148 );
149 }
150
151 #[test]
152 fn serialize_custom() {
153 let action = PusherKind::_Custom(CustomPusherData {
154 kind: "my.custom.kind".to_owned(),
155 data: JsonObject::new(),
156 });
157
158 assert_to_canonical_json_eq!(
159 action,
160 json!({
161 "kind": "my.custom.kind",
162 "data": {}
163 })
164 );
165 }
166
167 #[test]
168 fn deserialize_email() {
169 let json = json!({
171 "kind": "email",
172 "data": {},
173 });
174
175 assert_let!(PusherKind::Email(data) = from_json_value(json).unwrap());
176 assert!(data.data.is_empty());
177
178 let json = json!({
180 "kind": "email",
181 "data": {
182 "custom_key": "value",
183 },
184 });
185
186 assert_let!(PusherKind::Email(data) = from_json_value(json).unwrap());
187 assert_eq!(data.data.len(), 1);
188 assert_eq!(data.data["custom_key"], "value");
189 }
190
191 #[test]
192 fn deserialize_http() {
193 let json = json!({
195 "kind": "http",
196 "data": {
197 "url": "http://localhost",
198 },
199 });
200
201 assert_let!(PusherKind::Http(data) = from_json_value(json).unwrap());
202 assert_eq!(data.url, "http://localhost");
203 assert_eq!(data.format, None);
204 assert!(data.data.is_empty());
205
206 let json = json!({
208 "kind": "http",
209 "data": {
210 "url": "http://localhost",
211 "custom_key": "value",
212 },
213 });
214
215 assert_let!(PusherKind::Http(data) = from_json_value(json).unwrap());
216 assert_eq!(data.data.len(), 1);
217 assert_eq!(data.data["custom_key"], "value");
218 }
219
220 #[test]
221 fn deserialize_custom() {
222 let json = json!({
223 "kind": "my.custom.kind",
224 "data": {}
225 });
226
227 assert_let!(PusherKind::_Custom(custom) = from_json_value(json).unwrap());
228 assert_eq!(custom.kind, "my.custom.kind");
229 assert!(custom.data.is_empty());
230 }
231}