stree 0.1.0

A directory hierarchy mapping format, similar to mtree
Documentation
use std::fmt::{self, Debug, Display};
use std::str::FromStr;

#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};

use crate::{Error, Result, error};

/// Represents the various fundamental file types on unix like systems
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "kebab-case"))]
pub enum FileType
{
    /// Regular real files
    #[default]
    Regular,
    /// Directories/folders
    Directory,
    /// Symbolic links
    Symlink,
    /// Block special devices
    Block,
    /// Character special devices
    Character,
    /// Unix domain/tcp/udp sockets
    Socket,
    /// Named pipes
    Fifo
}

impl TryFrom<libc::mode_t> for FileType
{
    type Error = Error;
    fn try_from(m: libc::mode_t) -> Result<Self>
    {
        match m & libc::S_IFMT
        {
            libc::S_IFREG => Ok(Self::Regular),
            libc::S_IFDIR => Ok(Self::Directory),
            libc::S_IFLNK => Ok(Self::Symlink),
            libc::S_IFSOCK => Ok(Self::Socket),
            libc::S_IFCHR => Ok(Self::Character),
            libc::S_IFBLK => Ok(Self::Block),
            libc::S_IFIFO => Ok(Self::Fifo),
            _ => error!("unable to determine file type from libc::mode_t")
        }
    }
}

impl Display for FileType
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
    {
        write!(f, "{}", match self
        {
            Self::Regular => "regular",
            Self::Directory => "directory",
            Self::Symlink => "link",
            Self::Socket => "socket",
            Self::Fifo => "fifo",
            Self::Character => "character",
            Self::Block => "block"
        })
    }
}

impl FromStr for FileType
{
    type Err = Error;
    fn from_str(s: &str) -> Result<Self>
    {
        match s
        {
            "regular" => Ok(Self::Regular),
            "directory" => Ok(Self::Directory),
            "link" => Ok(Self::Symlink),
            "socket" => Ok(Self::Socket),
            "fifo" => Ok(Self::Fifo),
            "character" => Ok(Self::Character),
            "block" => Ok(Self::Block),
            _ => error!("unknown file type: '{s}'")
        }
    }
}