use std::marker::PhantomData;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll, ready};
use futures::{Stream, StreamExt};
use tokio::sync::mpsc;
use crate::client::Client;
use crate::error::{Error, Result};
use crate::row::{Column, Row};
pub(crate) enum Streamed {
Row(Row),
End,
}
pub struct RowStream<'a> {
columns: Arc<[Column]>,
rows: mpsc::Receiver<Result<Streamed>>,
finished: bool,
_client: PhantomData<&'a mut Client>,
}
impl std::fmt::Debug for RowStream<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RowStream")
.field("columns", &self.columns)
.field("finished", &self.finished)
.finish()
}
}
impl RowStream<'_> {
pub(crate) fn new(columns: Arc<[Column]>, rows: mpsc::Receiver<Result<Streamed>>) -> Self {
Self {
columns,
rows,
finished: false,
_client: PhantomData,
}
}
pub fn columns(&self) -> &[Column] {
&self.columns
}
pub async fn try_next(&mut self) -> Result<Option<Row>> {
self.next().await.transpose()
}
}
impl Stream for RowStream<'_> {
type Item = Result<Row>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if self.finished {
return Poll::Ready(None);
}
let last = match ready!(self.rows.poll_recv(cx)) {
Some(Ok(Streamed::Row(row))) => return Poll::Ready(Some(Ok(row))),
Some(Ok(Streamed::End)) => None,
Some(Err(e)) => Some(Err(e)),
None => Some(Err(Error::ConnectionClosed)),
};
self.finished = true;
Poll::Ready(last)
}
}
#[cfg(test)]
mod tests;