use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::time::UNIX_EPOCH;
use chrono::{DateTime, Utc};
use crate::config::FileKind;
pub struct File {
pub abs_dir: PathBuf,
pub rel_dir: PathBuf,
pub file_depth: usize,
pub file_name: String,
pub file_ext: String,
pub file_type: FileKind,
pub file_mode: u32,
pub owner_user: Option<Rc<String>>,
pub owner_group: Option<Rc<String>>,
pub file_size: u64,
pub file_time: DateTime<Utc>,
pub file_ver: Option<String>,
pub link_data: Option<(PathBuf, FileKind)>,
}
impl File {
pub fn new(
abs_dir: PathBuf,
rel_dir: PathBuf,
file_depth: usize,
file_name: String,
file_ext: String,
file_type: FileKind,
) -> File {
Self {
abs_dir,
rel_dir,
file_depth,
file_name,
file_ext,
file_type,
file_mode: 0,
owner_user: None,
owner_group: None,
file_size: 0,
file_time: DateTime::<Utc>::from(UNIX_EPOCH),
file_ver: None,
link_data: None,
}
}
pub fn with_mode(mut self, file_mode: u32) -> File {
self.file_mode = file_mode;
return self;
}
pub fn with_owner(
mut self,
owner_user: Option<Rc<String>>,
owner_group: Option<Rc<String>>,
) -> File {
self.owner_user = owner_user;
self.owner_group = owner_group;
return self;
}
#[cfg(debug_assertions)]
pub fn with_owner_ref(
mut self,
owner_user: &str,
owner_group: &str,
) -> File {
self.owner_user = Some(Rc::new(String::from(owner_user)));
self.owner_group = Some(Rc::new(String::from(owner_group)));
return self;
}
pub fn with_size(mut self, file_size: u64) -> File {
self.file_size = file_size;
return self;
}
pub fn with_time(mut self, file_time: DateTime<Utc>) -> File {
self.file_time = file_time;
return self;
}
#[cfg(test)]
pub fn with_date(mut self, year: i32, month: u32, day: u32) -> File {
use chrono::TimeZone;
self.file_time = Utc.with_ymd_and_hms(year, month, day, 0, 0, 0).unwrap();
return self;
}
pub fn with_version(mut self, file_ver: String) -> File {
self.file_ver = Some(file_ver);
return self;
}
pub fn with_link(mut self, link_path: PathBuf, link_type: FileKind) -> File {
self.link_data = Some((link_path, link_type));
return self;
}
pub fn get_path(&self) -> PathBuf {
self.abs_dir.join(&self.file_name)
}
pub fn select_dir(&self, abs_path: bool) -> &Path {
if abs_path {
&self.abs_dir
} else {
&self.rel_dir
}
}
pub fn select_parent_for_indent(&self) -> Option<&Path> {
if self.file_type == FileKind::Dir {
self.rel_dir.parent()
} else {
Some(&self.rel_dir)
}
}
pub fn select_name_for_indent(&self) -> Option<&str> {
if self.file_type == FileKind::Dir {
self.rel_dir.file_name().and_then(OsStr::to_str)
} else {
Some(&self.file_name)
}
}
pub fn group_dir_before_file(&self) -> u8 {
if self.file_type == FileKind::Dir { 0 } else { 1 }
}
}
impl PartialEq for File {
fn eq(&self, other: &Self) -> bool {
(self.abs_dir == other.abs_dir) && (self.file_name == other.file_name)
}
}
impl Eq for File {
}
impl Hash for File {
fn hash<H: Hasher>(&self, state: &mut H) {
self.abs_dir.hash(state);
self.file_name.hash(state);
}
}