use std::{
collections::{hash_map, HashMap},
ops::Deref,
sync::Arc,
};
use super::{ServeError, Track, TrackReader, TrackWriter};
use crate::util::State;
#[derive(Debug)]
pub struct Broadcast {
pub namespace: String,
}
impl Broadcast {
pub fn new(namespace: &str) -> Self {
Self {
namespace: namespace.to_owned(),
}
}
pub fn produce(self) -> (BroadcastWriter, BroadcastReader) {
let (send, recv) = State::init();
let info = Arc::new(self);
let writer = BroadcastWriter::new(send, info.clone());
let reader = BroadcastReader::new(recv, info);
(writer, reader)
}
}
struct BroadcastState {
tracks: HashMap<String, TrackReader>,
closed: Result<(), ServeError>,
}
impl BroadcastState {
pub fn get(&self, name: &str) -> Result<Option<TrackReader>, ServeError> {
match self.tracks.get(name) {
Some(track) => Ok(Some(track.clone())),
None => self.closed.clone().map(|_| None),
}
}
pub fn insert(&mut self, track: TrackReader) -> Result<(), ServeError> {
match self.tracks.entry(track.name.clone()) {
hash_map::Entry::Occupied(_) => return Err(ServeError::Duplicate),
hash_map::Entry::Vacant(v) => v.insert(track),
};
Ok(())
}
pub fn remove(&mut self, name: &str) -> Option<TrackReader> {
self.tracks.remove(name)
}
}
impl Default for BroadcastState {
fn default() -> Self {
Self {
tracks: HashMap::new(),
closed: Ok(()),
}
}
}
pub struct BroadcastWriter {
state: State<BroadcastState>,
pub info: Arc<Broadcast>,
}
impl BroadcastWriter {
fn new(state: State<BroadcastState>, broadcast: Arc<Broadcast>) -> Self {
Self { state, info: broadcast }
}
pub fn create_track(&mut self, track: &str) -> Result<TrackWriter, ServeError> {
let (writer, reader) = Track {
namespace: self.namespace.clone(),
name: track.to_owned(),
}
.produce();
self.state.lock_mut().ok_or(ServeError::Cancel)?.insert(reader)?;
Ok(writer)
}
pub fn remove_track(&mut self, track: &str) -> Option<TrackReader> {
self.state.lock_mut()?.remove(track)
}
pub fn close(self, err: ServeError) -> Result<(), ServeError> {
let state = self.state.lock();
state.closed.clone()?;
if let Some(mut state) = state.into_mut() {
state.closed = Err(err);
}
Ok(())
}
}
impl Deref for BroadcastWriter {
type Target = Broadcast;
fn deref(&self) -> &Self::Target {
&self.info
}
}
#[derive(Clone)]
pub struct BroadcastReader {
state: State<BroadcastState>,
pub info: Arc<Broadcast>,
}
impl BroadcastReader {
fn new(state: State<BroadcastState>, broadcast: Arc<Broadcast>) -> Self {
Self { state, info: broadcast }
}
pub fn get_track(&self, name: &str) -> Result<Option<TrackReader>, ServeError> {
self.state.lock().get(name)
}
}
impl Deref for BroadcastReader {
type Target = Broadcast;
fn deref(&self) -> &Self::Target {
&self.info
}
}