1use ruma_common::serde::from_raw_json_value;
2use serde::{de, ser::SerializeStruct, Deserialize, Serialize};
3use serde_json::value::RawValue as RawJsonValue;
4
5use super::{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 _ => from_raw_json_value(&json).map(Self::_Custom),
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use assert_matches2::assert_matches;
83 use ruma_common::{push::HttpPusherData, serde::JsonObject};
84 use serde_json::{
85 from_value as from_json_value, json, to_value as to_json_value, Value as JsonValue,
86 };
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_eq!(
97 to_json_value(action).unwrap(),
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_eq!(
109 to_json_value(action).unwrap(),
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_eq!(
126 to_json_value(action).unwrap(),
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_eq!(
140 to_json_value(action).unwrap(),
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_eq!(
159 to_json_value(action).unwrap(),
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_matches!(from_json_value(json).unwrap(), PusherKind::Email(data));
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_matches!(from_json_value(json).unwrap(), PusherKind::Email(data));
187 assert_eq!(data.data.len(), 1);
188 assert_matches!(data.data.get("custom_key"), Some(JsonValue::String(custom_value)));
189 assert_eq!(custom_value, "value");
190 }
191
192 #[test]
193 fn deserialize_http() {
194 let json = json!({
196 "kind": "http",
197 "data": {
198 "url": "http://localhost",
199 },
200 });
201
202 assert_matches!(from_json_value(json).unwrap(), PusherKind::Http(data));
203 assert_eq!(data.url, "http://localhost");
204 assert_eq!(data.format, None);
205 assert!(data.data.is_empty());
206
207 let json = json!({
209 "kind": "http",
210 "data": {
211 "url": "http://localhost",
212 "custom_key": "value",
213 },
214 });
215
216 assert_matches!(from_json_value(json).unwrap(), PusherKind::Http(data));
217 assert_eq!(data.data.len(), 1);
218 assert_matches!(data.data.get("custom_key"), Some(JsonValue::String(custom_value)));
219 assert_eq!(custom_value, "value");
220 }
221
222 #[test]
223 fn deserialize_custom() {
224 let json = json!({
225 "kind": "my.custom.kind",
226 "data": {}
227 });
228
229 assert_matches!(from_json_value(json).unwrap(), PusherKind::_Custom(custom));
230 assert_eq!(custom.kind, "my.custom.kind");
231 assert!(custom.data.is_empty());
232 }
233}