Skip to main content

ruma_client_api/push/
pusher_serde.rs

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        // With default data fields.
93        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        // With custom data fields.
105        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        // With default data fields.
122        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        // With custom data fields.
136        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        // With default data fields.
170        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        // With custom data fields.
179        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        // With default data fields.
194        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        // With custom data fields.
207        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}