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