use std::env;
use std::path::PathBuf;
#[cfg(windows)]
const PATH_SEP: char = ';';
#[cfg(not(windows))]
const PATH_SEP: char = ':';
pub fn discovery_paths() -> Vec<PathBuf> {
if let Some(over) = env::var_os("OXIDEAV_VFW_CODEC_PATH") {
return parse_path_list(&over);
}
default_discovery_paths()
}
fn default_discovery_paths() -> Vec<PathBuf> {
if let Some(d) = platform_default_codec_dir() {
vec![d]
} else {
Vec::new()
}
}
#[cfg(windows)]
fn platform_default_codec_dir() -> Option<PathBuf> {
if let Some(local) = env::var_os("LOCALAPPDATA") {
let p = PathBuf::from(local).join("oxideav").join("codecs");
return Some(p);
}
None
}
#[cfg(not(windows))]
fn platform_default_codec_dir() -> Option<PathBuf> {
if let Some(xdg) = env::var_os("XDG_DATA_HOME") {
let p = PathBuf::from(xdg).join("oxideav").join("codecs");
return Some(p);
}
if let Some(home) = env::var_os("HOME") {
let p = PathBuf::from(home)
.join(".local")
.join("share")
.join("oxideav")
.join("codecs");
return Some(p);
}
None
}
fn parse_path_list(value: &std::ffi::OsStr) -> Vec<PathBuf> {
let s = value.to_string_lossy();
s.split(PATH_SEP)
.filter(|s| !s.is_empty())
.map(PathBuf::from)
.collect()
}
pub fn cache_file_path() -> PathBuf {
if let Some(p) = platform_cache_dir() {
p.join("vfw-discovery.json")
} else {
PathBuf::from("vfw-discovery.json")
}
}
#[cfg(windows)]
fn platform_cache_dir() -> Option<PathBuf> {
if let Some(local) = env::var_os("LOCALAPPDATA") {
let p = PathBuf::from(local).join("oxideav").join("Cache");
return Some(p);
}
None
}
#[cfg(not(windows))]
fn platform_cache_dir() -> Option<PathBuf> {
if let Some(xdg) = env::var_os("XDG_CACHE_HOME") {
let p = PathBuf::from(xdg).join("oxideav");
return Some(p);
}
if let Some(home) = env::var_os("HOME") {
let p = PathBuf::from(home).join(".cache").join("oxideav");
return Some(p);
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::OsString;
#[test]
fn parse_empty_components_skipped() {
let s = OsString::from(format!("{0}/a{0}{0}/b{0}", PATH_SEP));
let v = parse_path_list(&s);
assert_eq!(v, vec![PathBuf::from("/a"), PathBuf::from("/b")]);
}
#[test]
fn parse_single_component() {
let s = OsString::from("/only/one");
let v = parse_path_list(&s);
assert_eq!(v, vec![PathBuf::from("/only/one")]);
}
#[test]
fn discovery_paths_honours_override() {
let saved = env::var_os("OXIDEAV_VFW_CODEC_PATH");
env::set_var(
"OXIDEAV_VFW_CODEC_PATH",
format!("/dev/null{0}/tmp/nonexistent", PATH_SEP),
);
let paths = discovery_paths();
assert_eq!(
paths,
vec![
PathBuf::from("/dev/null"),
PathBuf::from("/tmp/nonexistent"),
]
);
match saved {
Some(v) => env::set_var("OXIDEAV_VFW_CODEC_PATH", v),
None => env::remove_var("OXIDEAV_VFW_CODEC_PATH"),
}
}
#[test]
fn cache_file_path_basename() {
let p = cache_file_path();
assert_eq!(
p.file_name().and_then(|s| s.to_str()),
Some("vfw-discovery.json")
);
}
}