dirscent 0.1.0

Directory descent
Documentation
use std::fs::{FileType, Metadata};
use std::path::{Path, PathBuf};

use crate::error::Error;

/// Entries returned by the [iterator][crate::Dirscent].
pub struct DirEntry {
    path: PathBuf,
    file_type: FileType,
    follow_symlinks: bool,
}

impl DirEntry {
    /// Returns the full path to the file under the entry.
    pub fn path(&self) -> &Path {
        &self.path
    }

    /// Returns the file type of the file under the entry.
    ///
    /// This function does not traverse symlinks.
    pub fn file_type(&self) -> FileType {
        self.file_type
    }

    /// Returns the metadata for the file under the entry.
    ///
    /// Depending on the [iterator][crate::Dirscent] `follow_symlinks` option, this function is
    /// equivalent to [`std::fs::metadata`] or [`std::fs::symlink_metadata`].
    pub fn metadata(&self) -> Result<Metadata, Error> {
        if self.follow_symlinks {
            self.path.metadata()
        } else {
            self.path.symlink_metadata()
        }
        .map_err(|err| Error::new(err, self.path.clone()))
    }

    /// Sets whether the directory entry follows symlinks.
    ///
    /// If the argument is `true`, symlinks are followed.
    pub fn with_follow_symlinks(mut self, x: bool) -> Self {
        self.follow_symlinks = x;
        self
    }
}

impl TryFrom<std::fs::DirEntry> for DirEntry {
    type Error = Error;

    fn try_from(entry: std::fs::DirEntry) -> Result<Self, Self::Error> {
        let path = entry.path();
        match entry.file_type() {
            Ok(file_type) => Ok(DirEntry {
                path,
                file_type,
                follow_symlinks: false,
            }),
            Err(err) => Err(Error::new(err, path)),
        }
    }
}

impl TryFrom<PathBuf> for DirEntry {
    type Error = Error;

    fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
        match path.symlink_metadata().map(|m| m.file_type()) {
            Ok(file_type) => Ok(DirEntry {
                path,
                file_type,
                follow_symlinks: false,
            }),
            Err(err) => Err(Error::new(err, path)),
        }
    }
}