use std::future::Future;
use std::pin::Pin;
use std::task::ready;
use crate::client::Error;
use crate::message::{NameEntry, ReadDir, Status, StatusCode};
use super::Dir;
impl futures::Stream for Dir {
type Item = Result<NameEntry, Error>;
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
let Some(buffer) = &mut self.buffer else {
return std::task::Poll::Ready(None);
};
if let Some(entry) = buffer.0.pop() {
return std::task::Poll::Ready(Some(Ok(entry)));
}
let result = match &mut self.pending {
Some(pending) => {
ready!(Pin::new(pending).poll(cx))
}
None => {
let Some(handle) = &self.handle else {
self.buffer = None;
return std::task::Poll::Ready(Some(Err(std::io::Error::new(
std::io::ErrorKind::BrokenPipe,
"Dir was closed",
)
.into())));
};
let readdir = self.client.request(ReadDir {
handle: handle.clone(),
});
let pending = self.pending.insert(readdir);
ready!(Pin::new(pending).poll(cx))
}
};
self.pending = None;
self.buffer = None;
let result = match result {
Ok(mut entries) => {
entries.reverse();
if let Some(entry) = entries.0.pop() {
self.buffer = Some(entries);
Some(Ok(entry))
} else {
Some(Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"Found no more directory entries while it was expecting some",
)
.into()))
}
}
Err(Error::Sftp(Status {
code: StatusCode::Eof,
..
})) => None,
Err(err) => Some(Err(err)),
};
std::task::Poll::Ready(result)
}
}