use core::fmt;
use bitflags::bitflags;
use super::Permissions;
bitflags! {
#[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
pub struct Os9Attrs: u8 {
const R_USER = 0b00000001;
const W_USER = 0b00000010;
const E_USER = 0b00000100;
const PERM_USER = 0b00000111;
const R_OTHER = 0b00001000;
const W_OTHER = 0b00010000;
const E_OTHER = 0b00100000;
const PERM_OTHER = 0b00111000;
const N_SHAREABLE = 0b01000000;
const TYPE_DIR = 0b10000000;
}
}
impl Os9Attrs {
pub fn is_dir(self) -> bool {
self.intersects(Os9Attrs::TYPE_DIR)
}
pub fn is_file(self) -> bool {
!self.is_dir()
}
pub fn user(self) -> Self {
self.intersection(Os9Attrs::PERM_USER)
}
pub fn other(self) -> Self {
self.intersection(Os9Attrs::PERM_OTHER)
}
pub fn is_executable(self) -> bool {
self.intersects(Os9Attrs::E_OTHER|Os9Attrs::E_USER)
}
pub fn is_writable(self) -> bool {
self.intersects(Os9Attrs::W_OTHER|Os9Attrs::W_USER)
}
pub fn is_readable(self) -> bool {
self.intersects(Os9Attrs::R_OTHER|Os9Attrs::R_USER)
}
pub fn is_non_shareable(self) -> bool {
self.intersects(Os9Attrs::N_SHAREABLE)
}
}
impl fmt::Display for Os9Attrs {
#[inline(never)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut flags: [u8;8] = *b"--ewrewr";
if self.is_dir() {
flags[0] = b'd';
}
if self.is_non_shareable() {
flags[1] = b's';
}
let mut mask = Os9Attrs::PERM_OTHER;
for i in (2..=5).step_by(3) {
let perm = self.intersection(mask);
if !perm.is_executable() {
flags[i] = b'-';
}
if !perm.is_writable() {
flags[i + 1] = b'-';
}
if !perm.is_readable() {
flags[i + 2] = b'-';
}
mask = Os9Attrs::from_bits_retain(mask.bits() >> 3);
}
let flags = str::from_utf8(&flags).unwrap();
flags.fmt(f)
}
}
impl From<Os9Attrs> for Permissions {
fn from(attr: Os9Attrs) -> Permissions {
let mut perm = Permissions::empty();
let user = attr.user();
perm.set(Permissions::R_USER, user.is_readable());
perm.set(Permissions::W_USER, user.is_writable());
perm.set(Permissions::X_USER, user.is_executable());
let other = attr.other();
perm.set(Permissions::R_OTHER|Permissions::R_GROUP, other.is_readable());
perm.set(Permissions::W_OTHER|Permissions::W_GROUP, other.is_writable());
perm.set(Permissions::X_OTHER|Permissions::X_GROUP, other.is_executable());
perm.insert(if attr.is_dir() {
Permissions::TYPE_DIR
}
else {
Permissions::TYPE_FILE
});
perm
}
}
#[cfg(test)]
mod tests {
#[cfg(not(feature = "std"))]
use alloc::string::ToString;
use super::*;
#[test]
fn os_9_attributes_works() {
assert!(Os9Attrs::E_OTHER.is_executable());
assert!(Os9Attrs::W_OTHER.is_writable());
assert!(Os9Attrs::R_OTHER.is_readable());
assert!(Os9Attrs::E_OTHER.other().is_executable());
assert!(Os9Attrs::W_OTHER.other().is_writable());
assert!(Os9Attrs::R_OTHER.other().is_readable());
assert!(!Os9Attrs::E_OTHER.user().is_executable());
assert!(!Os9Attrs::W_OTHER.user().is_writable());
assert!(!Os9Attrs::R_OTHER.user().is_readable());
assert!(Os9Attrs::PERM_OTHER.is_executable());
assert!(Os9Attrs::PERM_OTHER.is_writable());
assert!(Os9Attrs::PERM_OTHER.is_readable());
assert!(Os9Attrs::PERM_OTHER.other().is_executable());
assert!(Os9Attrs::PERM_OTHER.other().is_writable());
assert!(Os9Attrs::PERM_OTHER.other().is_readable());
assert!(!Os9Attrs::PERM_OTHER.user().is_executable());
assert!(!Os9Attrs::PERM_OTHER.user().is_writable());
assert!(!Os9Attrs::PERM_OTHER.user().is_readable());
assert!(Os9Attrs::E_USER.is_executable());
assert!(Os9Attrs::W_USER.is_writable());
assert!(Os9Attrs::R_USER.is_readable());
assert!(Os9Attrs::E_USER.user().is_executable());
assert!(Os9Attrs::W_USER.user().is_writable());
assert!(Os9Attrs::R_USER.user().is_readable());
assert!(!Os9Attrs::E_USER.other().is_executable());
assert!(!Os9Attrs::W_USER.other().is_writable());
assert!(!Os9Attrs::R_USER.other().is_readable());
assert!(Os9Attrs::PERM_USER.is_executable());
assert!(Os9Attrs::PERM_USER.is_writable());
assert!(Os9Attrs::PERM_USER.is_readable());
assert!(Os9Attrs::PERM_USER.user().is_executable());
assert!(Os9Attrs::PERM_USER.user().is_writable());
assert!(Os9Attrs::PERM_USER.user().is_readable());
assert!(!Os9Attrs::PERM_USER.other().is_executable());
assert!(!Os9Attrs::PERM_USER.other().is_writable());
assert!(!Os9Attrs::PERM_USER.other().is_readable());
assert!(Os9Attrs::N_SHAREABLE.is_non_shareable());
assert!(Os9Attrs::TYPE_DIR.is_dir());
assert!(!Os9Attrs::TYPE_DIR.is_file());
assert!(!Os9Attrs::empty().is_executable());
assert!(!Os9Attrs::empty().is_writable());
assert!(!Os9Attrs::empty().is_readable());
assert!(!Os9Attrs::empty().other().is_executable());
assert!(!Os9Attrs::empty().other().is_writable());
assert!(!Os9Attrs::empty().other().is_readable());
assert!(!Os9Attrs::empty().user().is_executable());
assert!(!Os9Attrs::empty().user().is_writable());
assert!(!Os9Attrs::empty().user().is_readable());
assert!(!Os9Attrs::empty().is_non_shareable());
assert!(!Os9Attrs::empty().is_dir());
assert!(Os9Attrs::empty().is_file());
assert_eq!(Os9Attrs::empty().to_string(), "--------");
assert_eq!(Os9Attrs::R_USER.to_string(), "-------r");
assert_eq!(Os9Attrs::W_USER.to_string(), "------w-");
assert_eq!(Os9Attrs::E_USER.to_string(), "-----e--");
assert_eq!(Os9Attrs::PERM_USER.to_string(), "-----ewr");
assert_eq!(Os9Attrs::R_OTHER.to_string(), "----r---");
assert_eq!(Os9Attrs::W_OTHER.to_string(), "---w----");
assert_eq!(Os9Attrs::E_OTHER.to_string(), "--e-----");
assert_eq!(Os9Attrs::PERM_OTHER.to_string(), "--ewr---");
assert_eq!(Os9Attrs::N_SHAREABLE.to_string(), "-s------");
assert_eq!(Os9Attrs::TYPE_DIR.to_string(), "d-------");
assert_eq!((Os9Attrs::TYPE_DIR|
Os9Attrs::N_SHAREABLE|
Os9Attrs::PERM_OTHER|
Os9Attrs::PERM_USER).to_string(), "dsewrewr");
assert_eq!((Os9Attrs::N_SHAREABLE|
Os9Attrs::PERM_OTHER|
Os9Attrs::PERM_USER).to_string(), "-sewrewr");
assert_eq!((Os9Attrs::TYPE_DIR|
Os9Attrs::PERM_OTHER|
Os9Attrs::PERM_USER).to_string(), "d-ewrewr");
assert_eq!((Os9Attrs::TYPE_DIR|
Os9Attrs::N_SHAREABLE|
Os9Attrs::E_OTHER|
Os9Attrs::E_USER).to_string(), "dse--e--");
assert_eq!((Os9Attrs::N_SHAREABLE|
Os9Attrs::R_OTHER|
Os9Attrs::R_USER).to_string(), "-s--r--r");
assert_eq!((Os9Attrs::N_SHAREABLE|
Os9Attrs::W_OTHER|
Os9Attrs::W_USER).to_string(), "-s-w--w-");
assert_eq!((Os9Attrs::R_USER|
Os9Attrs::W_USER).to_string(), "------wr");
assert_eq!((Os9Attrs::R_OTHER|
Os9Attrs::W_OTHER).to_string(), "---wr---");
assert_eq!(Os9Attrs::all().to_string(), "dsewrewr");
for &(expected, perm) in &[
("drwxrwxrwx", Os9Attrs::TYPE_DIR|Os9Attrs::PERM_OTHER|Os9Attrs::PERM_USER),
("drwxrwxrwx", Os9Attrs::all()),
("----------", Os9Attrs::empty()),
("----------", Os9Attrs::N_SHAREABLE),
("-rwx------", Os9Attrs::PERM_USER),
("-r--------", Os9Attrs::R_USER),
("--w-------", Os9Attrs::W_USER),
("---x------", Os9Attrs::E_USER),
("----rwxrwx", Os9Attrs::PERM_OTHER),
("----r--r--", Os9Attrs::R_OTHER),
("-----w--w-", Os9Attrs::W_OTHER),
("------x--x", Os9Attrs::E_OTHER),
("drw-r--r--", Os9Attrs::TYPE_DIR|Os9Attrs::R_OTHER|Os9Attrs::W_USER|Os9Attrs::R_USER),
("-rwxr-xr-x", Os9Attrs::N_SHAREABLE|Os9Attrs::PERM_USER|Os9Attrs::R_OTHER|Os9Attrs::E_OTHER),
("drwxr-xr-x", Os9Attrs::TYPE_DIR|Os9Attrs::N_SHAREABLE|Os9Attrs::PERM_USER|Os9Attrs::R_OTHER|Os9Attrs::E_OTHER),
("-rwxr-xr-x", Os9Attrs::PERM_USER|Os9Attrs::R_OTHER|Os9Attrs::E_OTHER)]
{
assert_eq!(Permissions::from(perm).to_string(), expected);
}
}
}