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::{
63        DirectUserIdentifier, canonical_json::assert_to_canonical_json_eq, owned_room_id, user_id,
64    };
65    use serde_json::{from_value as from_json_value, json};
66
67    use super::{DirectEvent, DirectEventContent};
68
69    #[test]
70    fn serialization() {
71        let mut content = DirectEventContent(BTreeMap::new());
72        let alice = user_id!("@alice:ruma.io");
73        let alice_mail = "alice@ruma.io";
74        let rooms = vec![owned_room_id!("!1:ruma.io")];
75        let mail_rooms = vec![owned_room_id!("!3:ruma.io")];
76
77        content.insert(alice.into(), rooms.clone());
78        content.insert(alice_mail.into(), mail_rooms.clone());
79
80        let json_data = json!({
81            alice: rooms,
82            alice_mail: mail_rooms,
83        });
84
85        assert_to_canonical_json_eq!(content, json_data);
86    }
87
88    #[test]
89    fn deserialization() {
90        let alice = user_id!("@alice:ruma.io");
91        let alice_mail = "alice@ruma.io";
92        let rooms = vec![owned_room_id!("!1:ruma.io"), owned_room_id!("!2:ruma.io")];
93        let mail_rooms = vec![owned_room_id!("!3:ruma.io")];
94
95        let json_data = json!({
96            "content": {
97                alice: rooms,
98                alice_mail: mail_rooms,
99            },
100            "type": "m.direct"
101        });
102
103        let event: DirectEvent = from_json_value(json_data).unwrap();
104
105        let direct_rooms = event.content.get(<&DirectUserIdentifier>::from(alice)).unwrap();
106        assert!(direct_rooms.contains(&rooms[0]));
107        assert!(direct_rooms.contains(&rooms[1]));
108
109        let email_direct_rooms =
110            event.content.get(<&DirectUserIdentifier>::from(alice_mail)).unwrap();
111        assert!(email_direct_rooms.contains(&mail_rooms[0]));
112    }
113}