ruma_federation_api/
membership.rs1use ruma_common::serde::Raw;
4use ruma_events::AnyStrippedStateEvent;
5use serde::{Deserialize, Serialize};
6use serde_json::value::RawValue as RawJsonValue;
7
8pub mod create_invite;
9pub mod create_join_event;
10pub mod create_knock_event;
11pub mod create_leave_event;
12pub mod prepare_join_event;
13pub mod prepare_knock_event;
14pub mod prepare_leave_event;
15
16#[derive(Clone, Debug, Serialize)]
18#[serde(untagged)]
19#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
20pub enum RawStrippedState {
21 Stripped(Raw<AnyStrippedStateEvent>),
23
24 #[cfg(feature = "unstable-msc4311")]
26 Pdu(Box<RawJsonValue>),
27}
28
29impl<'de> Deserialize<'de> for RawStrippedState {
30 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31 where
32 D: ::serde::Deserializer<'de>,
33 {
34 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
35
36 #[cfg(feature = "unstable-msc4311")]
37 {
38 use ruma_common::serde::from_raw_json_value;
39 use serde::de;
40
41 #[derive(Deserialize)]
42 struct PotentialPduDeHelper {
43 auth_events: Option<de::IgnoredAny>,
44 prev_events: Option<de::IgnoredAny>,
45 signatures: Option<de::IgnoredAny>,
46 hashes: Option<de::IgnoredAny>,
47 }
48
49 let PotentialPduDeHelper { auth_events, prev_events, signatures, hashes } =
50 from_raw_json_value(&json)?;
51
52 if auth_events.is_some()
53 && prev_events.is_some()
54 && signatures.is_some()
55 && hashes.is_some()
56 {
57 return Ok(Self::Pdu(json));
58 }
59 }
60
61 Ok(Raw::from_json(json).into())
62 }
63}
64
65impl From<Raw<AnyStrippedStateEvent>> for RawStrippedState {
66 fn from(value: Raw<AnyStrippedStateEvent>) -> Self {
67 Self::Stripped(value)
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use assert_matches2::assert_matches;
74 use ruma_common::{serde::Raw, user_id};
75 use ruma_events::{room::member::MembershipState, AnyStrippedStateEvent};
76 use serde_json::{from_value as from_json_value, json};
77
78 use super::RawStrippedState;
79
80 #[test]
81 fn deserialize_stripped_state() {
82 let user_id = user_id!("@patrick:localhost");
83 let content = json!({
84 "membership": "join",
85 });
86
87 let stripped_event_json = json!({
89 "content": content,
90 "sender": user_id,
91 "state_key": user_id,
92 "type": "m.room.member",
93 });
94 assert_matches!(
95 from_json_value::<RawStrippedState>(stripped_event_json).unwrap(),
96 RawStrippedState::Stripped(raw_stripped_event)
97 );
98 assert_matches!(
99 raw_stripped_event.deserialize().unwrap(),
100 AnyStrippedStateEvent::RoomMember(stripped_member_event)
101 );
102 assert_eq!(stripped_member_event.sender, user_id);
103 assert_eq!(stripped_member_event.state_key, user_id);
104 assert_eq!(stripped_member_event.content.membership, MembershipState::Join);
105
106 #[cfg(feature = "unstable-msc4311")]
107 {
108 let pdu_event_json = json!({
110 "auth_events": [
111 "$one",
112 "$two",
113 "$three"
114 ],
115 "content": content,
116 "depth": 10,
117 "hashes": {
118 "sha256": "thisisahash"
119 },
120 "origin_server_ts": 1_000_000,
121 "prev_events": [
122 "$one",
123 "$two",
124 "$three"
125 ],
126 "room_id": "!room:localhost",
127 "sender": user_id,
128 "signatures": {
129 "localhost": {
130 "ed25519:1": "thisisakey"
131 }
132 },
133 "state_key": user_id,
134 "type": "m.room.member",
135 });
136 assert_matches!(
137 from_json_value::<RawStrippedState>(pdu_event_json).unwrap(),
138 RawStrippedState::Pdu(_pdu_member_event)
139 );
140 }
141 }
142
143 #[test]
144 fn serialize_stripped_state() {
145 let user_id = user_id!("@patrick:localhost");
146 let content = json!({
147 "membership": "join",
148 });
149
150 let stripped_event_json = json!({
152 "content": content,
153 "sender": user_id,
154 "state_key": user_id,
155 "type": "m.room.member",
156 });
157 let raw_stripped_event =
158 Raw::new(&stripped_event_json).unwrap().cast_unchecked::<AnyStrippedStateEvent>();
159 let stripped_state = RawStrippedState::from(raw_stripped_event);
160
161 let stripped_event_json = serde_json::to_string(&stripped_state).unwrap();
162 assert_eq!(
163 stripped_event_json,
164 r#"{"content":{"membership":"join"},"sender":"@patrick:localhost","state_key":"@patrick:localhost","type":"m.room.member"}"#
165 );
166 }
167}