use std::collections::{HashMap, HashSet};
use common::{InitError, PeerId, SessionId};
use crate::*;
#[derive(Default)]
#[cfg_attr(any(test, feature = "__tests"), derive(Clone))]
pub(crate) struct Sessions {
active: HashMap<SessionId, Session>,
}
impl Sessions {
#[cfg(any(test, feature = "__tests"))]
pub(crate) fn active(&self) -> &HashMap<SessionId, Session> {
&self.active
}
#[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))
}
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn remove_peer(&mut self, session_id: SessionId, peer_id: PeerId) {
let Some(session) = self.active.get_mut(&session_id) else {
return;
};
session.peers.remove(&peer_id);
if session.peers.is_empty() {
self.active.remove(&session_id);
}
}
#[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)
}
}
#[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 }
}
#[cfg(any(test, feature = "__tests"))]
pub(crate) fn peers(&self) -> &HashSet<PeerId> {
&self.peers
}
}