use indicatrix_formats::native::design::{
DESIGN_EXTENSION_DOTTED, design_path_for, is_design_path,
};
use std::path::{Path, PathBuf};
pub(super) const AUTOSAVE_INFIX: &str = ".autosave";
pub(super) const LEGACY_AUTOSAVE_SUFFIX: &str = ".indicatrix.autosave.toml";
fn stem_of(name: &str) -> &str {
Path::new(name)
.file_stem()
.and_then(|stem| stem.to_str())
.unwrap_or(name)
}
pub(super) fn design_file_name_for(schedule_name: &str) -> String {
design_path_for(stem_of(schedule_name))
.to_string_lossy()
.into_owned()
}
pub(super) fn ensure_design_extension(path: PathBuf) -> PathBuf {
if is_design_path(&path) {
return path;
}
let mut name = path.file_name().map_or_else(
|| std::ffi::OsString::from("design"),
std::ffi::OsStr::to_os_string,
);
name.push(DESIGN_EXTENSION_DOTTED);
path.with_file_name(name)
}
pub(super) fn is_autosave_design_path(path: &Path) -> bool {
is_design_path(path)
&& path
.file_stem()
.and_then(|stem| stem.to_str())
.is_some_and(|stem| stem.to_ascii_lowercase().ends_with(AUTOSAVE_INFIX))
}
pub(super) fn design_stem_of_path(path: &Path) -> Option<String> {
let stem = path.file_stem()?.to_str()?;
let trimmed = if stem.to_ascii_lowercase().ends_with(AUTOSAVE_INFIX) {
&stem[..stem.len() - AUTOSAVE_INFIX.len()]
} else {
stem
};
Some(trimmed.to_string())
}
pub(super) fn schedule_name_for_design_path(path: &Path) -> String {
format!(
"{}.asc",
design_stem_of_path(path).unwrap_or_else(|| "design".to_string())
)
}
pub(super) fn path_belongs_to_schedule_name(path: &Path, schedule_name: &str) -> bool {
is_design_path(path)
&& !is_autosave_design_path(path)
&& path
.file_stem()
.and_then(|stem| stem.to_str())
.is_some_and(|stem| stem.eq_ignore_ascii_case(stem_of(schedule_name)))
}
pub(super) fn autosave_file_name(schedule_name: Option<&str>) -> String {
format!(
"{}{AUTOSAVE_INFIX}{DESIGN_EXTENSION_DOTTED}",
autosave_base_name(schedule_name)
)
}
pub(super) fn legacy_autosave_file_name(schedule_name: Option<&str>) -> String {
format!(
"{}{LEGACY_AUTOSAVE_SUFFIX}",
autosave_base_name(schedule_name)
)
}
pub(super) fn autosave_base_name(schedule_name: Option<&str>) -> String {
let name = schedule_name.unwrap_or("untitled");
name.strip_suffix(".asc").unwrap_or(name).to_string()
}
pub(super) fn is_autosave_file_name(file_name: &str) -> bool {
let lower = file_name.to_ascii_lowercase();
lower.ends_with(LEGACY_AUTOSAVE_SUFFIX)
|| lower.ends_with(&format!("{AUTOSAVE_INFIX}{DESIGN_EXTENSION_DOTTED}"))
}