use crate::error::{MyError, MyResult};
use crate::fs::entry::Entry;
use crate::fs::flags::FileFlags;
use crate::fs::system::{System, EXEC_MASK};
use std::collections::HashSet;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ExecKind {
None,
User,
Other,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum FileKind {
File(ExecKind),
Dir,
Link(bool), Other,
}
impl FileKind {
fn from_char(ch: char) -> Option<Vec<Self>> {
match ch {
'f' => Some(vec![
Self::File(ExecKind::None),
Self::File(ExecKind::User),
Self::File(ExecKind::Other),
]),
'e' => Some(vec![
Self::File(ExecKind::User),
Self::File(ExecKind::Other),
]),
'd' => Some(vec![
Self::Dir,
]),
'l' => Some(vec![
Self::Link(false),
Self::Link(true),
]),
_ => None,
}
}
pub fn from_entry<S: System>(system: &S, entry: &dyn Entry) -> Self {
match entry.file_flags() {
FileFlags::File => Self::parse_file(system, entry),
FileFlags::Dir => Self::Dir,
FileFlags::Link => Self::Link(true),
FileFlags::Other => Self::Other,
}
}
#[cfg(unix)]
fn parse_file<S: System>(system: &S, entry: &dyn Entry) -> Self {
if (entry.file_mode() & system.get_mask(entry.owner_uid(), entry.owner_gid())) != 0 {
Self::File(ExecKind::User)
} else if (entry.file_mode() & EXEC_MASK) != 0 {
Self::File(ExecKind::Other)
} else {
Self::File(ExecKind::None)
}
}
#[cfg(not(unix))]
fn parse_file<S: System>(_system: &S, entry: &dyn Entry) -> Self {
if (entry.file_mode() & EXEC_MASK) != 0 {
Self::File(ExecKind::User)
} else {
Self::File(ExecKind::None)
}
}
pub fn dir_offset(&self) -> usize {
if *self == Self::Dir { 1 } else { 0 }
}
}
#[derive(Clone)]
pub struct FileSet {
pub inner: HashSet<FileKind>,
}
impl FileSet {
pub fn from_str(value: &str) -> MyResult<Self> {
let mut inner = HashSet::new();
for ch in value.chars() {
if let Some(items) = FileKind::from_char(ch) {
inner.extend(items);
} else {
return Err(MyError::create_clap("type", ch));
}
}
let results = Self { inner };
Ok(results)
}
}