1use js_int::UInt;
8use ruma_common::{
9 room::RoomType, serde::Raw, space::SpaceRoomJoinRule, EventEncryptionAlgorithm, OwnedMxcUri,
10 OwnedRoomAliasId, OwnedRoomId, RoomVersionId,
11};
12use ruma_events::space::child::HierarchySpaceChildEvent;
13use serde::{Deserialize, Serialize};
14
15pub mod get_hierarchy;
16
17#[derive(Clone, Debug, Deserialize, Serialize)]
22#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
23pub struct SpaceHierarchyRoomsChunk {
24 #[serde(skip_serializing_if = "Option::is_none")]
26 #[cfg_attr(
27 feature = "compat-empty-string-null",
28 serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
29 )]
30 pub canonical_alias: Option<OwnedRoomAliasId>,
31
32 #[serde(skip_serializing_if = "Option::is_none")]
34 pub name: Option<String>,
35
36 pub num_joined_members: UInt,
38
39 pub room_id: OwnedRoomId,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub topic: Option<String>,
45
46 pub world_readable: bool,
48
49 pub guest_can_join: bool,
53
54 #[serde(skip_serializing_if = "Option::is_none")]
59 #[cfg_attr(
60 feature = "compat-empty-string-null",
61 serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
62 )]
63 pub avatar_url: Option<OwnedMxcUri>,
64
65 #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
67 pub join_rule: SpaceRoomJoinRule,
68
69 #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
72 pub allowed_room_ids: Vec<OwnedRoomId>,
73
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub room_type: Option<RoomType>,
77
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub encryption: Option<EventEncryptionAlgorithm>,
81
82 #[serde(skip_serializing_if = "Option::is_none")]
84 pub room_version: Option<RoomVersionId>,
85
86 pub children_state: Vec<Raw<HierarchySpaceChildEvent>>,
90}
91
92#[derive(Debug)]
97#[allow(clippy::exhaustive_structs)]
98pub struct SpaceHierarchyRoomsChunkInit {
99 pub num_joined_members: UInt,
101
102 pub room_id: OwnedRoomId,
104
105 pub world_readable: bool,
107
108 pub guest_can_join: bool,
112
113 pub join_rule: SpaceRoomJoinRule,
115
116 pub children_state: Vec<Raw<HierarchySpaceChildEvent>>,
120}
121
122impl From<SpaceHierarchyRoomsChunkInit> for SpaceHierarchyRoomsChunk {
123 fn from(init: SpaceHierarchyRoomsChunkInit) -> Self {
124 let SpaceHierarchyRoomsChunkInit {
125 num_joined_members,
126 room_id,
127 world_readable,
128 guest_can_join,
129 join_rule,
130 children_state,
131 } = init;
132
133 Self {
134 canonical_alias: None,
135 name: None,
136 num_joined_members,
137 room_id,
138 topic: None,
139 world_readable,
140 guest_can_join,
141 avatar_url: None,
142 join_rule,
143 allowed_room_ids: Vec::new(),
144 room_type: None,
145 encryption: None,
146 room_version: None,
147 children_state,
148 }
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use serde_json::{from_value as from_json_value, json};
155
156 use super::SpaceHierarchyRoomsChunk;
157
158 #[test]
159 fn deserialize_space_hierarchy_rooms_chunk() {
160 let json = json!({
161 "room_id": "!room:localhost",
162 "num_joined_members": 5,
163 "world_readable": false,
164 "guest_can_join": false,
165 "join_rule": "restricted",
166 "allowed_room_ids": ["!otherroom:localhost"],
167 "children_state": [
168 {
169 "content": {
170 "via": [
171 "example.org"
172 ]
173 },
174 "origin_server_ts": 1_629_413_349,
175 "sender": "@alice:example.org",
176 "state_key": "!a:example.org",
177 "type": "m.space.child"
178 }
179 ],
180 });
181
182 let room = from_json_value::<SpaceHierarchyRoomsChunk>(json).unwrap();
183 assert_eq!(room.room_id, "!room:localhost");
184 let space_child = room.children_state[0].deserialize().unwrap();
185 assert_eq!(space_child.state_key, "!a:example.org");
186 }
187}