//! Permissions shit kms //! //! No I don't care about Microshaft wangblows #![allow(non_upper_case_globals)] use bitflags::bitflags; #[derive(Debug, Clone, PartialEq, Eq, Hash)] enum Class { Owner(Bit), Group(Bit), Other(Bit), } impl Class { /// Lmfao. Fuck bit masks and unix permissiong, `const fn` so idc const fn mode(&self) -> u32 { macro_rules! map { ($bit:expr, $bt:path, $constant:ident) => { if $bit.contains($bt) { $constant } else { 0 } } } match self { Self::Owner(bit) => { 0u32 | map!(bit, Bit::Read, MODE_USER_READ) | map!(bit, Bit::Write, MODE_USER_WRITE) | map!(bit, Bit::Execute, MODE_USER_EXECUTE) }, Self::Group(bit) => { 0u32 | map!(bit, Bit::Read, MODE_GROUP_READ) | map!(bit, Bit::Write, MODE_GROUP_WRITE) | map!(bit, Bit::Execute, MODE_GROUP_EXECUTE) }, Self::Other(bit) => { 0u32 | map!(bit, Bit::Read, MODE_OTHER_READ) | map!(bit, Bit::Write, MODE_OTHER_WRITE) | map!(bit, Bit::Execute, MODE_OTHER_EXECUTE) }, } } const fn mask_mode(&self, bit: u32) -> Bit { macro_rules! map { ($bit:expr, $bt:path, $constant:ident) => { if ($bit & $constant) == $constant {$bt.bits()} else {0u32} } } Bit::from_bits_truncate(match self { Self::Owner(_) => { map!(bit, Bit::Read, MODE_USER_READ) | map!(bit, Bit::Write, MODE_USER_WRITE) | map!(bit, Bit::Execute, MODE_USER_EXECUTE) }, Self::Group(_) => { map!(bit, Bit::Read, MODE_GROUP_READ) | map!(bit, Bit::Write, MODE_GROUP_WRITE) | map!(bit, Bit::Execute, MODE_GROUP_EXECUTE) }, Self::Other(_) => { map!(bit, Bit::Read, MODE_OTHER_READ) | map!(bit, Bit::Write, MODE_OTHER_WRITE) | map!(bit, Bit::Execute, MODE_OTHER_EXECUTE) }, }) } } const MODE_USER: u32 = 0o700; const MODE_USER_READ: u32 = 0o400; const MODE_USER_WRITE: u32 = 0o200; const MODE_USER_EXECUTE: u32 = 0o100; const MODE_GROUP: u32 = 0o70; const MODE_GROUP_READ: u32 = 0o40; const MODE_GROUP_WRITE: u32 = 0o20; const MODE_GROUP_EXECUTE: u32 = 0o10; const MODE_OTHER: u32 = 0o7; const MODE_OTHER_READ: u32 = 0o4; const MODE_OTHER_WRITE: u32 = 0o2; const MODE_OTHER_EXECUTE: u32 = 0o1; const MODE: u32 = 0o777; bitflags!{ pub struct Bit: u32 { const None = 0; const Read = 1; const Write = 2; const Execute = 4; const Mask = 7; } } bitflags!{ struct StickyBit: u32{ const None = 0; const Setuid = 0o40000; const Setgid = 0o20000; const SaveSwap = 0o10000; } } /// Permissions struct in readable format #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Ord, PartialOrd)] pub struct Permissions { pub u_owner: Bit, pub u_group: Bit, pub u_other: Bit, _u_sticky: StickyBit, //idc about this either } impl Default for Permissions { #[inline] fn default() -> Self { Self::new() } } impl Permissions { /// Create a new empty `Permissions` struct pub const fn new() -> Self { Self { u_owner: Bit::None, u_group: Bit::None, u_other: Bit::None, _u_sticky: StickyBit::None, } } } // Mask impl impl Permissions { #[inline] const fn c_owner(&self) -> Class { Class::Owner(self.u_owner) } #[inline] const fn c_group(&self) -> Class { Class::Group(self.u_group) } #[inline] const fn c_other(&self) -> Class { Class::Other(self.u_other) } /// Convert into `mode_t` repr. #[inline] pub const fn mask(&self) -> u32 { self.c_owner().mode() | self.c_group().mode() | self.c_other().mode() } /// Convert from `mode_t` repr. #[inline] pub const fn from_mask(bit: u32) -> Self { Self{ u_owner: Class::Owner(Bit::Mask).mask_mode(bit), u_group: Class::Group(Bit::Mask).mask_mode(bit), u_other: Class::Other(Bit::Mask).mask_mode(bit), _u_sticky: StickyBit::None, } } } impl From for u32 { #[inline] fn from(from: Permissions) -> Self { from.mask() } } impl From for Permissions { #[inline] fn from(from: u32) -> Self { Self::from_mask(from) } }