ruma_federation_api/serde/
pdu_process_response.rs1use std::collections::BTreeMap;
2
3use ruma_common::OwnedEventId;
4#[cfg(feature = "client")]
5use serde::de::{Deserializer, MapAccess, Visitor};
6#[cfg(feature = "server")]
7use serde::ser::{SerializeMap, Serializer};
8
9#[cfg_attr(feature = "client", derive(serde::Deserialize))]
10#[cfg_attr(feature = "server", derive(serde::Serialize))]
11struct WrappedError {
12 #[cfg_attr(feature = "server", serde(skip_serializing_if = "Option::is_none"))]
13 error: Option<String>,
14}
15
16#[cfg(feature = "server")]
17pub(crate) fn serialize<S>(
18 response: &BTreeMap<OwnedEventId, Result<(), String>>,
19 serializer: S,
20) -> Result<S::Ok, S::Error>
21where
22 S: Serializer,
23{
24 let mut map = serializer.serialize_map(Some(response.len()))?;
25 for (key, value) in response {
26 let wrapped_error = WrappedError { error: value.clone().err() };
27 map.serialize_entry(&key, &wrapped_error)?;
28 }
29 map.end()
30}
31
32#[cfg(feature = "client")]
33#[allow(clippy::type_complexity)]
34pub(crate) fn deserialize<'de, D>(
35 deserializer: D,
36) -> Result<BTreeMap<OwnedEventId, Result<(), String>>, D::Error>
37where
38 D: Deserializer<'de>,
39{
40 use std::fmt;
41
42 struct PduProcessResponseVisitor;
43
44 impl<'de> Visitor<'de> for PduProcessResponseVisitor {
45 type Value = BTreeMap<OwnedEventId, Result<(), String>>;
46
47 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48 formatter.write_str("A map of EventIds to a map of optional errors")
49 }
50
51 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
52 where
53 M: MapAccess<'de>,
54 {
55 let mut map = BTreeMap::new();
56
57 while let Some((key, value)) = access.next_entry::<OwnedEventId, WrappedError>()? {
58 let v = match value.error {
59 None => Ok(()),
60 Some(error) => Err(error),
61 };
62 map.insert(key, v);
63 }
64 Ok(map)
65 }
66 }
67
68 deserializer.deserialize_map(PduProcessResponseVisitor)
69}
70
71#[cfg(all(test, feature = "client"))]
72mod tests_client {
73 use ruma_common::event_id;
74 use serde_json::json;
75
76 use super::deserialize;
77
78 #[test]
79 fn deserialize_error() {
80 let json = json!({
81 "$someevent:matrix.org": { "error": "Some processing error." }
82 });
83
84 let response = deserialize(json).unwrap();
85 let event_id = event_id!("$someevent:matrix.org");
86
87 let event_response = response.get(event_id).unwrap().clone().unwrap_err();
88 assert_eq!(event_response, "Some processing error.");
89 }
90
91 #[test]
92 fn deserialize_null_error_is_ok() {
93 let json = json!({
94 "$someevent:matrix.org": { "error": null }
95 });
96
97 let response = deserialize(json).unwrap();
98 let event_id = event_id!("$someevent:matrix.org");
99
100 response.get(event_id).unwrap().as_ref().unwrap();
101 }
102
103 #[test]
104 fn deserialize_empty_error_is_err() {
105 let json = json!({
106 "$someevent:matrix.org": { "error": "" }
107 });
108
109 let response = deserialize(json).unwrap();
110 let event_id = event_id!("$someevent:matrix.org");
111
112 let event_response = response.get(event_id).unwrap().clone().unwrap_err();
113 assert_eq!(event_response, "");
114 }
115
116 #[test]
117 fn deserialize_ok() {
118 let json = json!({
119 "$someevent:matrix.org": {}
120 });
121 let response = deserialize(json).unwrap();
122 response.get(event_id!("$someevent:matrix.org")).unwrap().as_ref().unwrap();
123 }
124}
125
126#[cfg(all(test, feature = "server"))]
127mod tests_server {
128 use std::collections::BTreeMap;
129
130 use ruma_common::{OwnedEventId, owned_event_id};
131 use serde_json::{json, value::Serializer as JsonSerializer};
132
133 use super::serialize;
134
135 #[test]
136 fn serialize_error() {
137 let mut response: BTreeMap<OwnedEventId, Result<(), String>> = BTreeMap::new();
138 response
139 .insert(owned_event_id!("$someevent:matrix.org"), Err("Some processing error.".into()));
140
141 let serialized = serialize(&response, JsonSerializer).unwrap();
142 let json = json!({
143 "$someevent:matrix.org": { "error": "Some processing error." }
144 });
145 assert_eq!(serialized, json);
146 }
147
148 #[test]
149 fn serialize_ok() {
150 let mut response: BTreeMap<OwnedEventId, Result<(), String>> = BTreeMap::new();
151 response.insert(owned_event_id!("$someevent:matrix.org"), Ok(()));
152
153 let serialized = serialize(&response, serde_json::value::Serializer).unwrap();
154 let json = json!({
155 "$someevent:matrix.org": {}
156 });
157 assert_eq!(serialized, json);
158 }
159}