use super::hang::CatalogExt;
use super::{Estimator, Rendition, RenditionConfig};
pub trait IntoRendition<E: CatalogExt, D> {
type Config: RenditionConfig<E> + AsMut<D>;
fn into_rendition(self) -> Self::Config;
}
impl<E: CatalogExt, D, C: RenditionConfig<E> + AsMut<D>> IntoRendition<E, D> for C {
type Config = C;
fn into_rendition(self) -> C {
self
}
}
pub(crate) struct Listing {
rendition: Box<dyn Owned>,
estimator: Estimator,
}
trait Owned: Send + Sync {
fn name(&self) -> &str;
fn timestamp(&self) -> crate::Result<moq_net::Timestamp>;
fn estimate(&mut self, estimate: super::Estimate) -> crate::Result<()>;
}
impl<E: CatalogExt, C: RenditionConfig<E>> Owned for Rendition<E, C> {
fn name(&self) -> &str {
Rendition::name(self)
}
fn timestamp(&self) -> crate::Result<moq_net::Timestamp> {
Rendition::timestamp(self, None)
}
fn estimate(&mut self, estimate: super::Estimate) -> crate::Result<()> {
Rendition::estimate(self, estimate)
}
}
impl Listing {
pub(crate) fn new<E: CatalogExt, C: RenditionConfig<E>>(
mut rendition: Rendition<E, C>,
config: C,
) -> crate::Result<Self> {
rendition.set(config)?;
Ok(Self {
estimator: rendition.estimator(),
rendition: Box::new(rendition),
})
}
pub(crate) fn name(&self) -> &str {
self.rendition.name()
}
pub(crate) fn record(&mut self, bytes: usize, captured: Option<moq_net::Timestamp>) -> crate::Result<()> {
let now = self.rendition.timestamp()?;
let flush = captured.map(|captured| (captured, std::time::Instant::now()));
self.record_at(now, bytes, flush)
}
pub(crate) fn record_at(
&mut self,
now: moq_net::Timestamp,
bytes: usize,
flush: Option<(moq_net::Timestamp, std::time::Instant)>,
) -> crate::Result<()> {
self.estimator.cut(Some(now));
self.estimator.write(now, bytes);
if let Some((captured, written)) = flush {
self.estimator.flush(captured, written);
}
self.rendition.estimate(self.estimator.estimate())
}
}