use std::ffi::OsString;
use std::fs::{self, DirEntry as StdDirEntry, FileType, Metadata, ReadDir as StdReadDir};
use std::io;
#[cfg(unix)]
use std::os::unix::fs::DirEntryExt;
use std::path::{Path, PathBuf};
use futures::{Future, Poll, Stream};
pub fn read_dir<P>(path: P) -> ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
ReadDirFuture::new(path)
}
#[derive(Debug)]
pub struct ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
path: P,
}
impl<P> ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
fn new(path: P) -> ReadDirFuture<P> {
ReadDirFuture { path: path }
}
}
impl<P> Future for ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
type Item = ReadDir;
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, io::Error> {
::blocking_io(|| Ok(ReadDir(fs::read_dir(&self.path)?)))
}
}
#[derive(Debug)]
pub struct ReadDir(StdReadDir);
impl Stream for ReadDir {
type Item = DirEntry;
type Error = io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
::blocking_io(|| match self.0.next() {
Some(Err(err)) => Err(err),
Some(Ok(item)) => Ok(Some(DirEntry(item))),
None => Ok(None),
})
}
}
#[derive(Debug)]
pub struct DirEntry(StdDirEntry);
impl DirEntry {
pub fn into_std(self) -> StdDirEntry {
self.0
}
pub fn path(&self) -> PathBuf {
self.0.path()
}
pub fn file_name(&self) -> OsString {
self.0.file_name()
}
pub fn poll_metadata(&self) -> Poll<Metadata, io::Error> {
::blocking_io(|| self.0.metadata())
}
pub fn poll_file_type(&self) -> Poll<FileType, io::Error> {
::blocking_io(|| self.0.file_type())
}
}
#[cfg(unix)]
impl DirEntryExt for DirEntry {
fn ino(&self) -> u64 {
self.0.ino()
}
}