summaryrefslogtreecommitdiffstats
path: root/src/message_subscriptions.rs
blob: 17d924f1de83825d8fd66cdac4f5887f76ccf8da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::collections::HashMap;

use jid::BareJID;
use tokio::sync::mpsc::{self, Receiver};
use uuid::Uuid;

use crate::message::{ArcMacawMessage, MacawMessage};

pub struct MessageSubscriptions {
    all: HashMap<Uuid, mpsc::Sender<(BareJID, ArcMacawMessage)>>,
    subset: HashMap<BareJID, HashMap<Uuid, mpsc::Sender<ArcMacawMessage>>>,
}

impl MessageSubscriptions {
    pub fn new() -> Self {
        Self {
            all: HashMap::new(),
            subset: HashMap::new(),
        }
    }

    pub async fn broadcast(&mut self, to: BareJID, message: ArcMacawMessage) {
        // subscriptions to all
        let mut removals = Vec::new();
        for (id, sender) in &self.all {
            match sender.send((to.clone(), message.clone())).await {
                Ok(_) => {}
                Err(_) => {
                    removals.push(*id);
                }
            }
        }
        for removal in removals {
            self.all.remove(&removal);
        }

        // subscriptions to specific chat
        if let Some(subscribers) = self.subset.get_mut(&to) {
            let mut removals = Vec::new();
            for (id, sender) in &*subscribers {
                match sender.send(message.clone()).await {
                    Ok(_) => {}
                    Err(_) => {
                        removals.push(*id);
                    }
                }
            }
            for removal in removals {
                subscribers.remove(&removal);
            }
            if subscribers.is_empty() {
                self.subset.remove(&to);
            }
        }
    }

    pub fn subscribe_all(&mut self) -> (Uuid, Receiver<(BareJID, ArcMacawMessage)>) {
        let (send, recv) = mpsc::channel(10);
        let id = Uuid::new_v4();
        self.all.insert(id, send);
        (id, recv)
    }

    pub fn subscribe_chat(&mut self, chat: BareJID) -> (Uuid, Receiver<ArcMacawMessage>) {
        let (send, recv) = mpsc::channel(10);
        let id = Uuid::new_v4();
        if let Some(chat_subscribers) = self.subset.get_mut(&chat) {
            chat_subscribers.insert(id, send);
        } else {
            let hash_map = HashMap::from([(id, send)]);
            self.subset.insert(chat, hash_map);
        }
        (id, recv)
    }

    pub fn unsubscribe_all(&mut self, sub_id: Uuid) {
        self.all.remove(&sub_id);
    }

    pub fn unsubscribe_chat(&mut self, sub_id: Uuid, chat: BareJID) {
        if let Some(chat_subs) = self.subset.get_mut(&chat) {
            chat_subs.remove(&sub_id);
        }
    }
}