vahanafs/src/fs/permission.rs
2025-02-28 02:50:43 -06:00

399 lines
9.1 KiB
Rust

use char_enum::{char_enum_derive::FromChar, AsIter, FromChar, FromStrError, ToChar};
use enumflags2::{bitflags, BitFlag, FromBitsError};
use std::{error::Error, fmt::Display, num::ParseIntError, ops::BitOr, str::FromStr};
use enumflags2::BitFlags;
use crate::utils::MapWhileRefExt;
#[derive(Debug)]
pub struct ParseModeError(String);
impl ParseModeError {
pub fn from_bits(bits: &str) -> Self {
Self(format!("invalid mode: `{bits}`"))
}
}
impl Display for ParseModeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Error for ParseModeError {}
impl From<ParseIntError> for ParseModeError {
fn from(value: ParseIntError) -> Self {
Self(value.to_string())
}
}
impl From<FromBitsError<Mode>> for ParseModeError {
fn from(value: FromBitsError<Mode>) -> Self {
Self::from_bits(&value.invalid_bits().to_string())
}
}
#[bitflags]
#[repr(u16)]
#[derive(Clone, Copy, Debug)]
pub enum Mode {
IXOTH = 0x0001,
IWOTH = 0x0002,
IROTH = 0x0004,
IXGRP = 0x0010,
IWGRP = 0x0020,
IRGRP = 0x0040,
IXUSR = 0x0100,
IWUSR = 0x0200,
IRUSR = 0x0400,
ISVTX = 0x1000,
ISGID = 0x2000,
ISUID = 0x4000,
}
impl Display for Mode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_string())
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct ModeFlags(BitFlags<Mode>);
impl FromStr for ModeFlags {
type Err = ParseModeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let bits = u16::from_str(s)?;
Ok(Self(BitFlags::from_bits(bits)?))
}
}
impl Display for ModeFlags {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Copy, Debug, FromChar)]
pub enum Operator {
#[value = "-"]
Sub,
#[value = "+"]
Add,
#[value = "="]
Eq,
}
impl Operator {
pub fn split(s: &str) -> Option<(&str, char, &str)> {
let mut result = None;
for d in Operator::iter() {
if let Some((a, b)) = s.split_once(d) {
result = Some((a, d, b));
break;
}
}
result
}
}
#[bitflags]
#[repr(u8)]
#[derive(Clone, Copy, Debug, FromChar)]
pub enum SymbolicMode {
#[value = 'r']
Read,
#[value = 'w']
Write,
#[value = 'x']
Execute,
#[value = 'X']
Search,
#[value = 's']
SetId,
#[value = 't']
Sticky,
}
#[bitflags]
#[repr(u8)]
#[derive(Clone, Copy, Debug, FromChar)]
pub enum GroupId {
#[value = 'u']
User,
#[value = 'g']
Group,
#[value = 'o']
Other,
}
#[derive(Clone, Debug)]
pub struct Modes<T: BitFlag>(BitFlags<T>);
impl<T: BitFlag> Default for Modes<T> {
fn default() -> Self {
Modes(BitFlags::<T>::default())
}
}
impl<T: BitFlag + FromChar> FromStr for Modes<T> {
type Err = FromStrError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let flags = s
.chars()
.map_while_ref(|c: &char| T::from_char(*c))
.fold(BitFlags::default(), BitOr::bitor);
Ok(Self(flags))
}
}
impl<T: BitFlag + Display> Display for Modes<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut iter = self.0.iter();
if let Some(head) = iter.next() {
write!(f, "{head}")?;
for item in iter {
write!(f, "{item}")?;
}
}
Ok(())
}
}
#[derive(Debug)]
pub struct ParseSymbolicArgsError(FromStrError);
impl Display for ParseSymbolicArgsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Error for ParseSymbolicArgsError {}
impl From<ParseSymbolicArgsError> for FromStrError {
fn from(value: ParseSymbolicArgsError) -> Self {
value.0
}
}
impl From<FromStrError> for ParseSymbolicArgsError {
fn from(value: FromStrError) -> Self {
Self(value)
}
}
#[derive(Clone, Debug)]
pub enum SymbolicArgs {
Group(Modes<GroupId>),
Mode(Modes<SymbolicMode>),
}
impl FromStr for SymbolicArgs {
type Err = ParseSymbolicArgsError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match Modes::<SymbolicMode>::from_str(s) {
Ok(perms) => Ok(Self::Mode(perms)),
Err(_) => match Modes::<GroupId>::from_str(s) {
Ok(perms) => Ok(Self::Group(perms)),
Err(_) => Err(FromStrError::new(format!("{} is not a valid argument", s)).into()),
},
}
}
}
impl Display for SymbolicArgs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SymbolicArgs::Group(modes) => write!(f, "{modes}"),
SymbolicArgs::Mode(modes) => write!(f, "{modes}"),
}
}
}
#[derive(Clone, Debug)]
pub enum ParseSymbolicError {
Group(String),
Operator(String),
Mode(String),
}
impl Display for ParseSymbolicError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Group(e) => e,
Self::Operator(e) => e,
Self::Mode(e) => e,
}
)
}
}
impl Error for ParseSymbolicError {}
impl From<ParseSymbolicArgsError> for ParseSymbolicError {
fn from(value: ParseSymbolicArgsError) -> Self {
Self::Mode(value.to_string())
}
}
#[derive(Clone, Debug)]
pub struct SymbolicPermissions {
groups: Modes<GroupId>,
operator: Operator,
mode: SymbolicArgs,
}
impl SymbolicPermissions {
pub fn new(groups: Modes<GroupId>, operator: Operator, mode: SymbolicArgs) -> Self {
Self {
groups,
operator,
mode,
}
}
}
impl FromStr for SymbolicPermissions {
type Err = ParseSymbolicError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match Operator::split(s) {
Some((groups, operator, mode)) => {
let groups =
Modes::from_str(groups).map_err(|e| ParseSymbolicError::Group(e.to_string()));
let operator = Operator::from_char(operator)
.map_err(|o| ParseSymbolicError::Operator(o.to_string()));
let mode = SymbolicArgs::from_str(mode)?;
Ok(Self::new(groups?, operator?, mode))
}
None => Err(ParseSymbolicError::Operator(format!(
"received invalid permission syntax: {s}"
))),
}
}
}
impl Display for SymbolicPermissions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{}{}", self.groups, self.operator, self.mode)
}
}
#[derive(Clone, Debug)]
pub struct ParseOctalError(String);
impl Display for ParseOctalError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Error for ParseOctalError {}
impl From<ParseModeError> for ParseOctalError {
fn from(value: ParseModeError) -> Self {
Self(value.0)
}
}
#[derive(Clone, Debug, Default)]
pub struct OctalPermissions(ModeFlags);
impl Display for OctalPermissions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl FromStr for OctalPermissions {
type Err = ParseOctalError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(ModeFlags::from_str(s)?))
}
}
#[derive(Debug)]
pub enum ParsePermissionsError {
Symbolic(ParseSymbolicError),
Octal(ParseOctalError),
}
impl Display for ParsePermissionsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParsePermissionsError::Symbolic(e) => write!(f, "{e}"),
ParsePermissionsError::Octal(e) => write!(f, "{e}"),
}
}
}
impl Error for ParsePermissionsError {}
impl From<ParseSymbolicError> for ParsePermissionsError {
fn from(value: ParseSymbolicError) -> Self {
Self::Symbolic(value)
}
}
impl From<ParseOctalError> for ParsePermissionsError {
fn from(value: ParseOctalError) -> Self {
Self::Octal(value)
}
}
#[derive(Clone, Debug)]
pub enum Permissions {
Symbolic(SymbolicPermissions),
Octal(OctalPermissions),
}
impl FromStr for Permissions {
type Err = ParsePermissionsError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(SymbolicPermissions::from_str(s)
.map(Self::Symbolic)
.or_else(|_| OctalPermissions::from_str(s).map(Self::Octal))?)
}
}
impl Display for Permissions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Permissions::Symbolic(v) => write!(f, "{v}"),
Permissions::Octal(v) => write!(f, "{v}"),
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::Permissions;
#[test]
fn it_works() {
let a = Permissions::from_str("ug+w");
println!("{}", a.unwrap());
}
}