use std::task::Poll;
use bytes::Bytes;
use crate::Result;
pub use super::Config;
pub struct Consumer {
track: moq_net::track::Ordered,
group: Option<moq_net::group::Consumer>,
flate: Option<moq_flate::Decoder>,
compression: bool,
}
impl Consumer {
pub fn new(track: moq_net::track::Subscriber, config: Config) -> Self {
Self {
track: track.ordered(),
group: None,
flate: None,
compression: config.compression.is_deflate(),
}
}
pub async fn next(&mut self) -> Result<Option<Bytes>> {
kio::wait(|waiter| self.poll_next(waiter)).await
}
pub fn poll_next(&mut self, waiter: &kio::Waiter) -> Poll<Result<Option<Bytes>>> {
let track_finished = loop {
match self.track.poll_next_group(waiter)? {
Poll::Ready(Some(group)) => {
self.group = Some(group);
self.flate = self.compression.then(moq_flate::Decoder::new);
}
Poll::Ready(None) => break true,
Poll::Pending => break false,
}
};
let mut latest = None;
let mut group_pending = false;
while let Some(group) = &mut self.group {
match group.poll_read_frame(waiter) {
Poll::Ready(Ok(Some(frame))) => latest = Some(self.decode(&frame.payload)?),
Poll::Ready(Ok(None)) => {
self.group = None;
break;
}
Poll::Ready(Err(err)) => {
let sequence = group.sequence;
self.group = None;
tracing::warn!(
track = self.track.name(),
group = sequence,
error = ?err,
"snapshot group lost; waiting for a newer one"
);
break;
}
Poll::Pending => {
group_pending = true;
break;
}
}
}
if let Some(payload) = latest {
return Poll::Ready(Ok(Some(payload)));
}
if group_pending {
return Poll::Pending;
}
match track_finished {
true => Poll::Ready(Ok(None)),
false => Poll::Pending,
}
}
fn decode(&mut self, payload: &Bytes) -> Result<Bytes> {
Ok(match self.flate.as_mut() {
Some(flate) => flate.frame(payload)?,
None => payload.clone(),
})
}
}