use core::fmt;
use std::{ops::Deref, sync::Arc, time};
use crate::{Error, VarInt};
use bytes::Bytes;
use super::Watch;
pub fn new(info: Info) -> (Publisher, Subscriber) {
let state = Watch::new(State::default());
let info = Arc::new(info);
let publisher = Publisher::new(state.clone(), info.clone());
let subscriber = Subscriber::new(state, info);
(publisher, subscriber)
}
#[derive(Debug)]
pub struct Info {
pub sequence: VarInt,
pub priority: i32,
pub expires: Option<time::Duration>,
}
#[derive(Debug)]
struct State {
data: Vec<Bytes>,
closed: Result<(), Error>,
}
impl State {
pub fn close(&mut self, err: Error) -> Result<(), Error> {
self.closed?;
self.closed = Err(err);
Ok(())
}
}
impl Default for State {
fn default() -> Self {
Self {
data: Vec::new(),
closed: Ok(()),
}
}
}
pub struct Publisher {
state: Watch<State>,
info: Arc<Info>,
_dropped: Arc<Dropped>,
}
impl Publisher {
fn new(state: Watch<State>, info: Arc<Info>) -> Self {
let _dropped = Arc::new(Dropped::new(state.clone()));
Self { state, info, _dropped }
}
pub fn write_chunk(&mut self, data: Bytes) -> Result<(), Error> {
let mut state = self.state.lock_mut();
state.closed?;
state.data.push(data);
Ok(())
}
pub fn close(self, err: Error) -> Result<(), Error> {
self.state.lock_mut().close(err)
}
}
impl Deref for Publisher {
type Target = Info;
fn deref(&self) -> &Self::Target {
&self.info
}
}
impl fmt::Debug for Publisher {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Publisher")
.field("state", &self.state)
.field("info", &self.info)
.finish()
}
}
#[derive(Clone)]
pub struct Subscriber {
state: Watch<State>,
info: Arc<Info>,
index: usize,
_dropped: Arc<Dropped>,
}
impl Subscriber {
fn new(state: Watch<State>, info: Arc<Info>) -> Self {
let _dropped = Arc::new(Dropped::new(state.clone()));
Self {
state,
info,
index: 0,
_dropped,
}
}
pub async fn read_chunk(&mut self) -> Result<Option<Bytes>, Error> {
loop {
let notify = {
let state = self.state.lock();
if self.index < state.data.len() {
let chunk = state.data[self.index].clone();
self.index += 1;
return Ok(Some(chunk));
}
match state.closed {
Err(Error::Closed) => return Ok(None),
Err(err) => return Err(err),
Ok(()) => state.changed(),
}
};
notify.await; }
}
}
impl Deref for Subscriber {
type Target = Info;
fn deref(&self) -> &Self::Target {
&self.info
}
}
impl fmt::Debug for Subscriber {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Subscriber")
.field("state", &self.state)
.field("info", &self.info)
.field("index", &self.index)
.finish()
}
}
struct Dropped {
state: Watch<State>,
}
impl Dropped {
fn new(state: Watch<State>) -> Self {
Self { state }
}
}
impl Drop for Dropped {
fn drop(&mut self) {
self.state.lock_mut().close(Error::Closed).ok();
}
}