use crate::inode::InodeMode;
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct FileTypeError;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum FileType {
BlockDevice,
CharacterDevice,
Directory,
Fifo,
Regular,
Socket,
Symlink,
}
impl FileType {
pub(crate) fn from_dir_entry(val: u8) -> Result<Self, FileTypeError> {
match val {
1 => Ok(Self::Regular),
2 => Ok(Self::Directory),
3 => Ok(Self::CharacterDevice),
4 => Ok(Self::BlockDevice),
5 => Ok(Self::Fifo),
6 => Ok(Self::Socket),
7 => Ok(Self::Symlink),
_ => Err(FileTypeError),
}
}
#[must_use]
pub fn is_block_dev(self) -> bool {
self == Self::BlockDevice
}
#[must_use]
pub fn is_char_dev(self) -> bool {
self == Self::CharacterDevice
}
#[must_use]
pub fn is_dir(self) -> bool {
self == Self::Directory
}
#[must_use]
pub fn is_fifo(self) -> bool {
self == Self::Fifo
}
#[must_use]
pub fn is_regular_file(self) -> bool {
self == Self::Regular
}
#[must_use]
pub fn is_socket(self) -> bool {
self == Self::Socket
}
#[must_use]
pub fn is_symlink(self) -> bool {
self == Self::Symlink
}
}
impl TryFrom<InodeMode> for FileType {
type Error = FileTypeError;
fn try_from(mode: InodeMode) -> Result<Self, Self::Error> {
let mode = InodeMode::from_bits_retain(mode.bits() & 0xf000);
if mode == InodeMode::S_IFIFO {
Ok(Self::Fifo)
} else if mode == InodeMode::S_IFCHR {
Ok(Self::CharacterDevice)
} else if mode == InodeMode::S_IFDIR {
Ok(Self::Directory)
} else if mode == InodeMode::S_IFBLK {
Ok(Self::BlockDevice)
} else if mode == InodeMode::S_IFREG {
Ok(Self::Regular)
} else if mode == InodeMode::S_IFLNK {
Ok(Self::Symlink)
} else if mode == InodeMode::S_IFSOCK {
Ok(Self::Socket)
} else {
Err(FileTypeError)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_file_type() {
assert!(FileType::try_from(InodeMode::S_IFIFO).unwrap().is_fifo());
assert!(FileType::try_from(InodeMode::S_IFCHR)
.unwrap()
.is_char_dev());
assert!(FileType::try_from(InodeMode::S_IFBLK)
.unwrap()
.is_block_dev());
assert!(FileType::try_from(InodeMode::S_IFREG)
.unwrap()
.is_regular_file());
assert!(FileType::try_from(InodeMode::S_IFLNK).unwrap().is_symlink());
assert!(FileType::try_from(InodeMode::S_IFSOCK).unwrap().is_socket());
assert!(FileType::try_from(InodeMode::S_IFREG | InodeMode::S_IXOTH)
.unwrap()
.is_regular_file());
assert_eq!(
FileType::try_from(InodeMode::empty()).unwrap_err(),
FileTypeError
);
}
}