ruma_federation_api/serde/
v1_pdu.rs1#[cfg(feature = "client")]
12use std::{fmt, marker::PhantomData};
13
14#[cfg(feature = "client")]
15use serde::de::{Deserialize, Deserializer, Error, IgnoredAny, SeqAccess, Visitor};
16#[cfg(feature = "server")]
17use serde::ser::{Serialize, SerializeSeq, Serializer};
18
19#[cfg(feature = "server")]
20pub(crate) fn serialize<T, S>(val: &T, serializer: S) -> Result<S::Ok, S::Error>
21where
22 S: Serializer,
23 T: Serialize,
24{
25 let mut seq = serializer.serialize_seq(Some(2))?;
26 seq.serialize_element(&200)?;
27 seq.serialize_element(val)?;
28 seq.end()
29}
30
31#[cfg(feature = "client")]
32pub(crate) fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
33where
34 D: Deserializer<'de>,
35 T: Deserialize<'de>,
36{
37 deserializer.deserialize_seq(PduVisitor { phantom: PhantomData })
38}
39
40#[cfg(feature = "client")]
41struct PduVisitor<T> {
42 phantom: PhantomData<T>,
43}
44
45#[cfg(feature = "client")]
46impl<'de, T> Visitor<'de> for PduVisitor<T>
47where
48 T: Deserialize<'de>,
49{
50 type Value = T;
51
52 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
53 formatter.write_str("a PDU wrapped in an array.")
54 }
55
56 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
57 where
58 A: SeqAccess<'de>,
59 {
60 let expected = "a two-element list in the response";
61 if seq.next_element::<IgnoredAny>()?.is_none() {
62 return Err(A::Error::invalid_length(0, &expected));
63 }
64
65 let val = seq.next_element()?.ok_or_else(|| A::Error::invalid_length(1, &expected))?;
66
67 while let Some(IgnoredAny) = seq.next_element()? {
68 }
70
71 Ok(val)
72 }
73}
74
75#[cfg(all(test, feature = "client"))]
76mod tests_client {
77 use assert_matches2::assert_matches;
78 use serde_json::json;
79
80 use super::deserialize;
81 #[allow(deprecated)]
82 use crate::membership::create_join_event::v1::RoomState;
83
84 #[test]
85 fn deserialize_response() {
86 let response = json!([
87 200,
88 {
89 "auth_chain": [],
90 "state": []
91 }
92 ]);
93
94 #[allow(deprecated)]
95 let RoomState { auth_chain, state, event } = deserialize(response).unwrap();
96 assert_matches!(auth_chain.as_slice(), []);
97 assert_matches!(state.as_slice(), []);
98 assert_matches!(event, None);
99 }
100
101 #[test]
102 fn too_short_array() {
103 let json = json!([200]);
104 #[allow(deprecated)]
105 let failed_room_state = deserialize::<RoomState, _>(json);
106 assert_eq!(
107 failed_room_state.unwrap_err().to_string(),
108 "invalid length 1, expected a two-element list in the response"
109 );
110 }
111
112 #[test]
113 fn not_an_array() {
114 let json = json!({
115 "origin": "matrix.org",
116 "auth_chain": [],
117 "state": []
118 });
119 #[allow(deprecated)]
120 let failed_room_state = deserialize::<RoomState, _>(json);
121
122 assert_eq!(
123 failed_room_state.unwrap_err().to_string(),
124 "invalid type: map, expected a PDU wrapped in an array.",
125 );
126 }
127
128 #[test]
129 fn too_long_array() {
130 let json = json!([200, { "auth_chain": [], "state": [] }, 200]);
131 #[allow(deprecated)]
132 let RoomState { auth_chain, state, event } = deserialize(json).unwrap();
133 assert_matches!(auth_chain.as_slice(), []);
134 assert_matches!(state.as_slice(), []);
135 assert_matches!(event, None);
136 }
137}
138
139#[cfg(all(test, feature = "server"))]
140mod tests_server {
141 use serde_json::json;
142
143 use super::serialize;
144 #[allow(deprecated)]
145 use crate::membership::create_join_event::v1::RoomState;
146
147 #[test]
148 fn serialize_response() {
149 #[allow(deprecated)]
150 let room_state = RoomState { auth_chain: Vec::new(), state: Vec::new(), event: None };
151
152 let serialized = serialize(&room_state, serde_json::value::Serializer).unwrap();
153 let expected = json!(
154 [
155 200,
156 {
157 "auth_chain": [],
158 "state": []
159 }
160 ]
161 );
162
163 assert_eq!(serialized, expected);
164 }
165}