use crate::error::FirebaseError;
use crate::firestore::document_snapshot::DocumentSnapshot;
use crate::firestore::query_snapshot::QuerySnapshot;
use futures::Stream;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::sync::{mpsc, oneshot};
pub struct DocumentSnapshotStream {
receiver: mpsc::UnboundedReceiver<Result<DocumentSnapshot, FirebaseError>>,
cancel_tx: Option<oneshot::Sender<()>>,
}
impl DocumentSnapshotStream {
pub(crate) fn new(
receiver: mpsc::UnboundedReceiver<Result<DocumentSnapshot, FirebaseError>>,
cancel_tx: oneshot::Sender<()>,
) -> Self {
Self {
receiver,
cancel_tx: Some(cancel_tx),
}
}
}
impl Stream for DocumentSnapshotStream {
type Item = Result<DocumentSnapshot, FirebaseError>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.receiver.poll_recv(cx)
}
}
impl Drop for DocumentSnapshotStream {
fn drop(&mut self) {
if let Some(tx) = self.cancel_tx.take() {
let _ = tx.send(());
}
}
}
pub struct QuerySnapshotStream {
receiver: mpsc::UnboundedReceiver<Result<QuerySnapshot, FirebaseError>>,
cancel_tx: Option<oneshot::Sender<()>>,
}
impl QuerySnapshotStream {
pub(crate) fn new(
receiver: mpsc::UnboundedReceiver<Result<QuerySnapshot, FirebaseError>>,
cancel_tx: oneshot::Sender<()>,
) -> Self {
Self {
receiver,
cancel_tx: Some(cancel_tx),
}
}
}
impl Stream for QuerySnapshotStream {
type Item = Result<QuerySnapshot, FirebaseError>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.receiver.poll_recv(cx)
}
}
impl Drop for QuerySnapshotStream {
fn drop(&mut self) {
if let Some(tx) = self.cancel_tx.take() {
let _ = tx.send(());
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_document_snapshot_stream_drop_cancels() {
use futures::StreamExt;
let (tx, rx) = mpsc::unbounded_channel();
let (cancel_tx, mut cancel_rx) = oneshot::channel();
{
let _stream = DocumentSnapshotStream::new(rx, cancel_tx);
}
assert!(cancel_rx.try_recv().is_ok());
assert!(tx.is_closed());
}
#[tokio::test]
async fn test_query_snapshot_stream_drop_cancels() {
use futures::StreamExt;
let (tx, rx) = mpsc::unbounded_channel();
let (cancel_tx, mut cancel_rx) = oneshot::channel();
{
let _stream = QuerySnapshotStream::new(rx, cancel_tx);
}
assert!(cancel_rx.try_recv().is_ok());
assert!(tx.is_closed());
}
}