#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CompatibilityMode {
#[default]
Default,
Strict,
}
pub fn resolve(argv: &[String]) -> CompatibilityMode {
if argv.iter().any(|a| a == "--no-strict") {
return CompatibilityMode::Default;
}
if argv.iter().any(|a| a == "--strict") {
return CompatibilityMode::Strict;
}
if std::env::var("RUSTY_PV_STRICT").as_deref() == Ok("1") {
return CompatibilityMode::Strict;
}
if let Some(first) = argv.first() {
let base = basename(first);
if base.eq_ignore_ascii_case("pv") || base.eq_ignore_ascii_case("pv-alias") {
return CompatibilityMode::Strict;
}
}
CompatibilityMode::Default
}
pub fn basename(path: &str) -> &str {
let last = path
.rsplit_once(['/', '\\'])
.map(|(_, b)| b)
.unwrap_or(path);
last.strip_suffix(".exe").unwrap_or(last)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn explicit_strict_flag() {
let argv = vec!["rusty-pv".into(), "--strict".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Strict);
}
#[test]
fn no_strict_overrides_strict_flag() {
let argv = vec!["rusty-pv".into(), "--strict".into(), "--no-strict".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Default);
}
#[test]
fn argv0_pv_triggers_strict() {
let argv = vec!["/usr/local/bin/pv".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Strict);
}
#[test]
fn argv0_pv_alias_triggers_strict() {
let argv = vec!["pv-alias".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Strict);
}
#[test]
fn argv0_rusty_pv_is_default() {
let argv = vec!["rusty-pv".into()];
assert_eq!(resolve(&argv), CompatibilityMode::Default);
}
#[test]
fn basename_strips_exe_on_windows_path() {
assert_eq!(basename("C:\\bin\\pv.exe"), "pv");
assert_eq!(basename("/usr/bin/pv"), "pv");
assert_eq!(basename("pv"), "pv");
}
}