matrix_sdk/event_handler/
maps.rs1use std::{
16 borrow::Borrow,
17 collections::{btree_map, BTreeMap},
18};
19
20use ruma::{OwnedRoomId, RoomId};
21
22use super::{EventHandlerFn, EventHandlerHandle, EventHandlerWrapper, HandlerKind};
23
24#[derive(Default)]
25pub(super) struct EventHandlerMaps {
26 by_kind: BTreeMap<HandlerKind, Vec<EventHandlerWrapper>>,
27 by_kind_type: BTreeMap<KindTypeWrap, Vec<EventHandlerWrapper>>,
28 by_kind_roomid: BTreeMap<KindRoomId, Vec<EventHandlerWrapper>>,
29 by_kind_type_roomid: BTreeMap<KindTypeRoomIdWrap, Vec<EventHandlerWrapper>>,
30}
31
32impl EventHandlerMaps {
33 pub fn add(&mut self, handle: EventHandlerHandle, handler_fn: Box<EventHandlerFn>) {
34 let wrapper = EventHandlerWrapper { handler_id: handle.handler_id, handler_fn };
35
36 match Key::new(handle) {
37 Key::Kind(key) => {
38 self.by_kind.entry(key).or_default().push(wrapper);
39 }
40 Key::KindType(key) => {
41 self.by_kind_type.entry(key).or_default().push(wrapper);
42 }
43 Key::KindRoomId(key) => {
44 self.by_kind_roomid.entry(key).or_default().push(wrapper);
45 }
46 Key::KindTypeRoomId(key) => {
47 self.by_kind_type_roomid.entry(key).or_default().push(wrapper)
48 }
49 }
50 }
51
52 pub fn get_handlers<'a>(
53 &'a self,
54 ev_kind: HandlerKind,
55 ev_type: &str,
56 room_id: Option<&'a RoomId>,
57 ) -> impl Iterator<Item = (EventHandlerHandle, &'a EventHandlerFn)> + 'a {
58 let kind_kv = self.by_kind.get_key_value(&ev_kind).map(|(_, handlers)| (None, handlers));
61 let kind_type_kv = self
62 .by_kind_type
63 .get_key_value(&KindType { ev_kind, ev_type })
64 .map(|(key, handlers)| (Some(key.0.ev_type), handlers));
65 let maybe_roomid_kvs = room_id
66 .map(|r_id| {
67 let room_id = r_id.to_owned();
68 let kind_roomid_kv = self
69 .by_kind_roomid
70 .get_key_value(&KindRoomId { ev_kind, room_id })
71 .map(|(_, handlers)| (None, handlers));
72
73 let room_id = r_id.to_owned();
74 let kind_type_roomid_kv = self
75 .by_kind_type_roomid
76 .get_key_value(&KindTypeRoomId { ev_kind, ev_type, room_id })
77 .map(|(key, handlers)| (Some(key.0.ev_type), handlers));
78
79 [kind_roomid_kv, kind_type_roomid_kv]
80 })
81 .into_iter()
82 .flatten();
83
84 [kind_kv, kind_type_kv].into_iter().chain(maybe_roomid_kvs).flatten().flat_map(
85 move |(ev_type, handlers)| {
86 handlers.iter().map(move |wrap| {
87 let handle = EventHandlerHandle {
88 ev_kind,
89 ev_type,
90 room_id: room_id.map(ToOwned::to_owned),
91 handler_id: wrap.handler_id,
92 };
93
94 (handle, &*wrap.handler_fn)
95 })
96 },
97 )
98 }
99
100 pub fn remove(&mut self, handle: EventHandlerHandle) {
101 fn remove_entry<K: Ord>(
103 map: &mut BTreeMap<K, Vec<EventHandlerWrapper>>,
104 key: K,
105 handler_id: u64,
106 ) {
107 if let btree_map::Entry::Occupied(mut o) = map.entry(key) {
108 let v = o.get_mut();
109 v.retain(|e| e.handler_id != handler_id);
110
111 if v.is_empty() {
112 o.remove();
113 }
114 }
115 }
116
117 let handler_id = handle.handler_id;
118 match Key::new(handle) {
119 Key::Kind(key) => {
120 remove_entry(&mut self.by_kind, key, handler_id);
121 }
122 Key::KindType(key) => {
123 remove_entry(&mut self.by_kind_type, key, handler_id);
124 }
125 Key::KindRoomId(key) => {
126 remove_entry(&mut self.by_kind_roomid, key, handler_id);
127 }
128 Key::KindTypeRoomId(key) => {
129 remove_entry(&mut self.by_kind_type_roomid, key, handler_id);
130 }
131 }
132 }
133
134 #[cfg(test)]
135 pub fn len(&self) -> usize {
136 self.by_kind_type.len() + self.by_kind_type_roomid.len()
137 }
138}
139
140enum Key {
141 Kind(HandlerKind),
142 KindType(KindTypeWrap),
143 KindRoomId(KindRoomId),
144 KindTypeRoomId(KindTypeRoomIdWrap),
145}
146
147impl Key {
148 fn new(handle: EventHandlerHandle) -> Self {
149 let EventHandlerHandle { ev_kind, ev_type, room_id, .. } = handle;
150 match (ev_type, room_id) {
151 (None, None) => Key::Kind(ev_kind),
152 (Some(ev_type), None) => Key::KindType(KindTypeWrap(KindType { ev_kind, ev_type })),
153 (None, Some(room_id)) => Key::KindRoomId(KindRoomId { ev_kind, room_id }),
154 (Some(ev_type), Some(room_id)) => {
155 let inner = KindTypeRoomId { ev_kind, ev_type, room_id };
156 Key::KindTypeRoomId(KindTypeRoomIdWrap(inner))
157 }
158 }
159 }
160}
161
162#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
163struct KindTypeWrap(KindType<'static>);
164
165#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
166struct KindType<'a> {
167 ev_kind: HandlerKind,
168 ev_type: &'a str,
169}
170
171#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
172struct KindRoomId {
173 ev_kind: HandlerKind,
174 room_id: OwnedRoomId,
175}
176
177#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
178struct KindTypeRoomIdWrap(KindTypeRoomId<'static>);
179
180#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
181struct KindTypeRoomId<'a> {
182 ev_kind: HandlerKind,
183 ev_type: &'a str,
184 room_id: OwnedRoomId,
185}
186
187impl<'a> Borrow<KindType<'a>> for KindTypeWrap {
190 fn borrow(&self) -> &KindType<'a> {
191 &self.0
192 }
193}
194
195impl<'a> Borrow<KindTypeRoomId<'a>> for KindTypeRoomIdWrap {
196 fn borrow(&self) -> &KindTypeRoomId<'a> {
197 &self.0
198 }
199}