use crate::category_util::owners::{OwnersKind, OwnersKind::*};
use crate::category_util::permssion_conver_util::*;
use crate::FullPermissionError;
use crate::ModeParser;
use regex::Regex;
use std::cell::RefCell;
use std::fmt::{Display, Formatter};
#[derive(Debug, Eq, PartialEq)]
pub struct FullPermission {
file_type: char,
user: OwnersKind,
group: OwnersKind,
other: OwnersKind,
}
impl FullPermission {
pub fn new(mode: u32) -> Result<Self, FullPermissionError> {
let mode_oc = format!("{:06o}", mode);
if mode_oc.len() != 6 {
return Err(FullPermissionError::new(format!("the mode that was provided is \
not valid 6 digit decimal number that can be parsed correctly into octal mode :{mode_oc}")));
}
let file_type = file_type_number_to_symbol(&mode_oc[0..=2]);
let user = digit_to_permission(&mode_oc[3..=3]); let group = digit_to_permission(&mode_oc[4..=4]);
let other = digit_to_permission(&mode_oc[5..=5]);
Ok(Self {
file_type,
user: User(RefCell::new(ModeParser::from(user))),
group: Group(RefCell::new(ModeParser::from(group))),
other: Other(RefCell::new(ModeParser::from(other))),
})
}
pub fn get_file_type(&self) -> char {
self.file_type
}
pub fn get_user(&mut self) -> &mut OwnersKind {
&mut self.user
}
pub fn get_group(&mut self) -> &mut OwnersKind {
&mut self.group
}
pub fn get_other(&mut self) -> &mut OwnersKind {
&mut self.other
}
pub fn get_mode(&mut self) -> u32 {
let num = symbol_to_file_type_number(self.get_file_type());
let user = self.user.get_partial_mode(); let group = self.group.get_partial_mode(); let other = self.other.get_partial_mode();
u32::from_str_radix(&format!("{num}{user}{group}{other}"), 8).unwrap_or(0)
}
pub fn mode_as_octal(&mut self) -> String {
format!("{:06o}", self.get_mode())
}
}
impl Display for FullPermission {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}{}{}{}",
self.file_type, self.user, self.group, self.other
)
}
}
pub struct FullPermissionBuilder {
mode: String,
}
impl FullPermissionBuilder {
pub fn new() -> Self {
Self {
mode: "".to_string(),
}
}
fn common_set_perm(&self, kind: &str, perm: &str) {
let reg = Regex::new("^[r-][w-][x-]$").unwrap();
if !reg.is_match(perm) {
panic!("{kind} permission must be a valid type only one of the options: rwx-")
}
}
pub fn file_type(&mut self, file_type: char) -> &mut Self {
let reg = Regex::new("^[-dlcbps]$").unwrap();
if !reg.is_match(&file_type.to_string()) {
panic!("file type must be a valid type only one of the options: -dlcbps")
}
self.mode.push_str(&symbol_to_file_type_number(file_type));
self
}
pub fn user(&mut self, user: &str) -> &mut Self {
self.common_set_perm("user", user);
self.mode.push_str(&permission_to_digit(user));
self
}
pub fn group(&mut self, group: &str) -> &mut Self {
self.common_set_perm("group", group);
self.mode.push_str(&permission_to_digit(group));
self
}
pub fn other(&mut self, other: &str) -> &mut Self {
self.common_set_perm("other", other);
self.mode.push_str(&permission_to_digit(other));
self
}
fn get_mode(&self) -> u32 {
u32::from_str_radix(&self.mode, 8).unwrap_or(0)
}
pub fn build(&self) -> Result<FullPermission, FullPermissionError> {
FullPermission::new(self.get_mode())
}
}
impl Default for FullPermissionBuilder {
fn default() -> Self {
FullPermissionBuilder::new()
}
}
impl Display for FullPermissionBuilder {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.get_mode())
}
}