Skip to main content

ruma_events/
direct.rs

1//! Types for the [`m.direct`] event.
2//!
3//! [`m.direct`]: https://spec.matrix.org/v1.19/client-server-api/#mdirect
4
5use std::{
6    collections::{BTreeMap, btree_map},
7    ops::{Deref, DerefMut},
8};
9
10use ruma_common::OwnedRoomId;
11pub use ruma_common::{DirectUserIdentifier, OwnedDirectUserIdentifier};
12use ruma_macros::EventContent;
13use serde::{Deserialize, Serialize};
14
15/// The content of an `m.direct` event.
16///
17/// A mapping of `DirectUserIdentifier`s to a list of `RoomId`s which are considered *direct*
18/// for that particular user.
19///
20/// Informs the client about the rooms that are considered direct by a user.
21#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
22#[allow(clippy::exhaustive_structs)]
23#[ruma_event(type = "m.direct", kind = GlobalAccountData)]
24pub struct DirectEventContent(pub BTreeMap<OwnedDirectUserIdentifier, Vec<OwnedRoomId>>);
25
26impl Deref for DirectEventContent {
27    type Target = BTreeMap<OwnedDirectUserIdentifier, Vec<OwnedRoomId>>;
28
29    fn deref(&self) -> &Self::Target {
30        &self.0
31    }
32}
33
34impl DerefMut for DirectEventContent {
35    fn deref_mut(&mut self) -> &mut Self::Target {
36        &mut self.0
37    }
38}
39
40impl IntoIterator for DirectEventContent {
41    type Item = (OwnedDirectUserIdentifier, Vec<OwnedRoomId>);
42    type IntoIter = btree_map::IntoIter<OwnedDirectUserIdentifier, Vec<OwnedRoomId>>;
43
44    fn into_iter(self) -> Self::IntoIter {
45        self.0.into_iter()
46    }
47}
48
49impl FromIterator<(OwnedDirectUserIdentifier, Vec<OwnedRoomId>)> for DirectEventContent {
50    fn from_iter<T>(iter: T) -> Self
51    where
52        T: IntoIterator<Item = (OwnedDirectUserIdentifier, Vec<OwnedRoomId>)>,
53    {
54        Self(BTreeMap::from_iter(iter))
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use std::collections::BTreeMap;
61
62    use ruma_common::{canonical_json::assert_to_canonical_json_eq, owned_room_id, user_id};
63    use serde_json::{from_value as from_json_value, json};
64
65    use super::{DirectEvent, DirectEventContent};
66
67    #[test]
68    fn serialization() {
69        let mut content = DirectEventContent(BTreeMap::new());
70        let alice = user_id!("@alice:ruma.io");
71        let alice_mail = "alice@ruma.io";
72        let rooms = vec![owned_room_id!("!1:ruma.io")];
73        let mail_rooms = vec![owned_room_id!("!3:ruma.io")];
74
75        content.insert(alice.into(), rooms.clone());
76        content.insert(alice_mail.into(), mail_rooms.clone());
77
78        let json_data = json!({
79            alice: rooms,
80            alice_mail: mail_rooms,
81        });
82
83        assert_to_canonical_json_eq!(content, json_data);
84    }
85
86    #[test]
87    fn deserialization() {
88        let alice = user_id!("@alice:ruma.io");
89        let alice_mail = "alice@ruma.io";
90        let rooms = vec![owned_room_id!("!1:ruma.io"), owned_room_id!("!2:ruma.io")];
91        let mail_rooms = vec![owned_room_id!("!3:ruma.io")];
92
93        let json_data = json!({
94            "content": {
95                alice: rooms,
96                alice_mail: mail_rooms,
97            },
98            "type": "m.direct"
99        });
100
101        let event: DirectEvent = from_json_value(json_data).unwrap();
102
103        let direct_rooms = event.content.get(alice.as_str()).unwrap();
104        assert!(direct_rooms.contains(&rooms[0]));
105        assert!(direct_rooms.contains(&rooms[1]));
106
107        let email_direct_rooms = event.content.get(alice_mail).unwrap();
108        assert!(email_direct_rooms.contains(&mail_rooms[0]));
109    }
110}