mirror of
https://github.com/YGGverse/titanit.git
synced 2026-03-31 17:15:30 +00:00
88 lines
2.6 KiB
Rust
88 lines
2.6 KiB
Rust
use anyhow::{bail, Result};
|
|
use std::{
|
|
fs::{create_dir_all, remove_file, rename, File},
|
|
path::{PathBuf, MAIN_SEPARATOR},
|
|
thread,
|
|
time::{Duration, SystemTime, UNIX_EPOCH},
|
|
};
|
|
|
|
const TMP_SUFFIX: &str = ".tmp";
|
|
|
|
pub struct Item {
|
|
pub file: File,
|
|
pub path: PathBuf,
|
|
// pub id: u64,
|
|
}
|
|
|
|
impl Item {
|
|
// Constructors
|
|
|
|
pub fn create(directory: &str) -> Result<Self> {
|
|
loop {
|
|
// generate file id from current unix time
|
|
let id = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
|
|
|
|
// build optimized fs path:
|
|
// add directory separator after every digit to keep up to 10 files per directory
|
|
let path = PathBuf::from(format!(
|
|
"{}{MAIN_SEPARATOR}{}{TMP_SUFFIX}",
|
|
directory.trim_end_matches(MAIN_SEPARATOR),
|
|
id.to_string().chars().fold(String::new(), |mut acc, c| {
|
|
if !acc.is_empty() {
|
|
acc.push(MAIN_SEPARATOR);
|
|
}
|
|
acc.push(c);
|
|
acc
|
|
})
|
|
));
|
|
|
|
// recursively create directories
|
|
// * parent directory is expected
|
|
create_dir_all(path.parent().unwrap())?;
|
|
|
|
// build `Self`
|
|
match File::create_new(&path) {
|
|
// make sure slot is not taken (by another thread)
|
|
Ok(file) => {
|
|
return Ok(Self {
|
|
file,
|
|
path,
|
|
// id
|
|
});
|
|
}
|
|
Err(_) => {
|
|
println!("[warning] Could not init location: {:?}", path.to_str());
|
|
// find free slot after some delay..
|
|
thread::sleep(Duration::from_secs(1));
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actions
|
|
|
|
/// Take object processed, commit its changes
|
|
pub fn commit(self) -> Result<String> {
|
|
match self.path.to_str() {
|
|
Some(old) => match old.strip_suffix(TMP_SUFFIX) {
|
|
Some(new) => {
|
|
rename(old, new)?;
|
|
Ok(new.to_string())
|
|
}
|
|
None => bail!("Invalid TMP suffix"), // | panic
|
|
},
|
|
None => bail!("Invalid Item path"), // | panic
|
|
}
|
|
}
|
|
|
|
/// Cleanup object relationships
|
|
pub fn delete(self) -> Result<()> {
|
|
Ok(remove_file(self.path)?)
|
|
}
|
|
|
|
// Getters
|
|
|
|
/* @TODO implement short links handle without slash
|
|
pub fn alias(&self, relative: &str) -> String {} */
|
|
}
|