use std::{
fmt,
pin::Pin,
task::{Context, Poll, ready},
};
use futures_util::Stream;
use crate::error::RecvError;
pub mod sync {
use super::*;
use crate::{future_store::sync::BoxedFutureStore, sync::Receiver};
async fn mk_fut<T: 'static + Clone + Send + Sync>(
rx: Receiver<T>,
) -> (Result<(), RecvError>, Receiver<T>) {
let result = rx.changed().await;
(result, rx)
}
pub struct SyncStream<T> {
inner: BoxedFutureStore<'static, (Result<(), RecvError>, Receiver<T>)>,
}
impl<T: 'static + Clone + Send + Sync> SyncStream<T> {
pub fn new(rx: Receiver<T>) -> Self {
Self {
inner: BoxedFutureStore::new(async move { (Ok(()), rx) }),
}
}
pub fn from_changes(rx: Receiver<T>) -> Self {
Self {
inner: BoxedFutureStore::new(mk_fut(rx)),
}
}
}
impl<T: Clone + 'static + Send + Sync> Stream for SyncStream<T> {
type Item = T;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let (result, mut rx) = ready!(self.inner.poll(cx));
match result {
Ok(_) => {
let received = (*rx.borrow_and_update()).clone();
self.inner.set(mk_fut(rx));
Poll::Ready(Some(received))
}
Err(_) => {
self.inner.set(mk_fut(rx));
Poll::Ready(None)
}
}
}
}
impl<T> Unpin for SyncStream<T> {}
impl<T> fmt::Debug for SyncStream<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SyncStream").finish()
}
}
impl<T: 'static + Clone + Send + Sync> From<Receiver<T>> for SyncStream<T> {
fn from(recv: Receiver<T>) -> Self {
Self::new(recv)
}
}
}
pub mod unsync {
use super::*;
use crate::{future_store::unsync::LocalBoxedFutureStore, unsync::Receiver};
async fn mk_fut<T: 'static + Clone>(rx: Receiver<T>) -> (Result<(), RecvError>, Receiver<T>) {
let result = rx.changed().await;
(result, rx)
}
pub struct UnsyncStream<T> {
inner: LocalBoxedFutureStore<'static, (Result<(), RecvError>, Receiver<T>)>,
}
impl<T: 'static + Clone> UnsyncStream<T> {
pub fn new(rx: Receiver<T>) -> Self {
Self {
inner: LocalBoxedFutureStore::new(async move { (Ok(()), rx) }),
}
}
pub fn from_changes(rx: Receiver<T>) -> Self {
Self {
inner: LocalBoxedFutureStore::new(mk_fut(rx)),
}
}
}
impl<T: Clone + 'static> Stream for UnsyncStream<T> {
type Item = T;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let (result, mut rx) = ready!(self.inner.poll(cx));
match result {
Ok(_) => {
let received = (*rx.borrow_and_update()).clone();
self.inner.set(mk_fut(rx));
Poll::Ready(Some(received))
}
Err(_) => {
self.inner.set(mk_fut(rx));
Poll::Ready(None)
}
}
}
}
impl<T> Unpin for UnsyncStream<T> {}
impl<T> fmt::Debug for UnsyncStream<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("UnsyncStream").finish()
}
}
impl<T: 'static + Clone> From<Receiver<T>> for UnsyncStream<T> {
fn from(recv: Receiver<T>) -> Self {
Self::new(recv)
}
}
}