use anyhow::Result;
use chrono::prelude::*;
use std::path::PathBuf;
pub trait FileTree {
fn basepath_fileprefix(&mut self, file_suffix: &str) -> Result<(PathBuf, PathBuf)>;
}
pub struct DateTimeDirTree {
basepath_fmt: String,
filename_prefix_fmt: String,
timestamp: Option<DateTime<FixedOffset>>,
}
impl DateTimeDirTree {
pub fn new(basepath_fmt: &str, filename_prefix_fmt: &str) -> Self {
Self {
basepath_fmt: basepath_fmt.to_owned(),
filename_prefix_fmt: filename_prefix_fmt.to_owned(),
timestamp: None,
}
}
pub fn set_timestamp<T: Into<DateTime<FixedOffset>>>(&mut self, ts: T) {
self.timestamp = Some(ts.into());
}
}
impl Default for DateTimeDirTree {
fn default() -> Self {
Self {
basepath_fmt: "%Y/%m/%d/%H/".to_string(),
filename_prefix_fmt: "%Y-%m-%d_%H-%M-%S-%3f_".to_string(),
timestamp: None,
}
}
}
impl FileTree for DateTimeDirTree {
fn basepath_fileprefix(&mut self, file_suffix: &str) -> Result<(PathBuf, PathBuf)> {
let now = self.timestamp.unwrap_or_else(|| Utc::now().into());
let basepath = now.format(&self.basepath_fmt).to_string();
let filename = now.format(&self.filename_prefix_fmt).to_string() + file_suffix;
Ok((basepath.into(), filename.into()))
}
}
#[derive(Default)]
pub struct CountingTree {
dir_counter: usize,
file_counter: usize,
max_in_dir: usize,
pub id: String,
}
impl CountingTree {
pub fn new(max_in_dir: usize) -> Self {
CountingTree {
max_in_dir,
..Default::default()
}
}
}
impl FileTree for CountingTree {
fn basepath_fileprefix(&mut self, file_suffix: &str) -> Result<(PathBuf, PathBuf)> {
let basepath: PathBuf = [self.id.as_ref(), self.dir_counter.to_string().as_str()]
.iter()
.collect();
let filename = self.file_counter.to_string() + file_suffix;
if self.file_counter + 1 > self.max_in_dir {
self.file_counter = 0;
self.dir_counter += 1;
} else {
self.file_counter += 1;
}
Ok((basepath, filename.into()))
}
}