collab-server 0.0.7

Nomad's collab server
Documentation
use std::collections::{HashMap, HashSet};

use common::{InitError, PeerId, SessionId};

use crate::*;

/// TODO: docs
#[derive(Default)]
#[cfg_attr(any(test, feature = "__tests"), derive(Clone))]
pub(crate) struct Sessions {
    active: HashMap<SessionId, Session>,
}

impl Sessions {
    /// TODO: docs
    #[cfg(any(test, feature = "__tests"))]
    pub(crate) fn active(&self) -> &HashMap<SessionId, Session> {
        &self.active
    }

    /// TODO: docs
    #[inline]
    pub fn join(
        &mut self,
        session_id: SessionId,
        peer_id: PeerId,
    ) -> Result<PeerSender, InitError> {
        let Some(session) = self.active.get_mut(&session_id) else {
            return Err(InitError::SessionDoesNotExist(session_id));
        };

        session.add_peer(peer_id)?;

        Ok(session.sender.fork(peer_id))
    }

    /// TODO: docs
    #[inline]
    pub fn new() -> Self {
        Self::default()
    }

    /// Removes the peer from the given session.
    ///
    /// If the peer was the last in the session, the session itself is also
    /// removed.
    #[inline]
    pub fn remove_peer(&mut self, session_id: SessionId, peer_id: PeerId) {
        let Some(session) = self.active.get_mut(&session_id) else {
            // TODO: log the error.
            return;
        };

        session.peers.remove(&peer_id);

        if session.peers.is_empty() {
            self.active.remove(&session_id);
        }
    }

    /// TODO: docs
    #[inline]
    pub fn start(
        &mut self,
        peer_id: PeerId,
    ) -> (SessionId, PeerSender, PeerReceiver) {
        let id = SessionId::new_random();
        let (sender, receiver) = broadcast::channel(16);
        let sender = PeerSender::new(sender, peer_id);
        let receiver = PeerReceiver::new(receiver, peer_id);
        let session = Session::new(peer_id, sender.clone());
        self.active.insert(id, session);
        (id, sender, receiver)
    }
}

/// TODO: docs
#[cfg_attr(any(test, feature = "__tests"), derive(Clone))]
pub(crate) struct Session {
    sender: PeerSender,
    peers: HashSet<PeerId>,
}

impl Session {
    #[inline]
    fn add_peer(&mut self, peer: PeerId) -> Result<(), InitError> {
        if self.peers.contains(&peer) {
            return Err(InitError::PeerAlreadyPresent(peer));
        }

        self.peers.insert(peer);

        Ok(())
    }

    #[inline]
    fn new(first_peer: PeerId, sender: PeerSender) -> Self {
        let mut peers = HashSet::new();
        peers.insert(first_peer);
        Self { sender, peers }
    }

    /// TODO: docs
    #[cfg(any(test, feature = "__tests"))]
    pub(crate) fn peers(&self) -> &HashSet<PeerId> {
        &self.peers
    }
}