use std::path::PathBuf;
use windows::Win32::System::Com::CoTaskMemFree;
use windows::Win32::UI::Shell::{FOLDERID_LocalAppData, KF_FLAG_DEFAULT, SHGetKnownFolderPath};
use crate::constants::STORE_SUBDIR;
use crate::pal::error::{PalError, PalErrorKind};
pub(crate) fn resolve_store_root(override_root: Option<PathBuf>) -> Result<PathBuf, PalError> {
if let Some(root) = override_root {
return Ok(root);
}
default_store_root()
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg_attr(test, mutants::skip)]
fn default_store_root() -> Result<PathBuf, PalError> {
windows_local_app_data().map(|root| root.join(STORE_SUBDIR))
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg_attr(test, mutants::skip)]
fn windows_local_app_data() -> Result<PathBuf, PalError> {
let pwstr = unsafe { SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, None) }
.map_err(|_error| PalError::new(PalErrorKind::Other))?;
let path = {
let wide = unsafe { pwstr.as_wide() };
String::from_utf16(wide)
.map(PathBuf::from)
.map_err(|_error| PalError::new(PalErrorKind::Other))?
};
unsafe {
CoTaskMemFree(Some(pwstr.0.cast()));
}
Ok(path)
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
#[test]
fn override_root_is_used_verbatim() {
let root = PathBuf::from("/tmp/dure-store");
assert_eq!(resolve_store_root(Some(root.clone())).unwrap(), root);
}
#[test]
#[cfg_attr(miri, ignore)]
fn without_an_override_the_default_root_is_used() {
let root = resolve_store_root(None).unwrap();
assert!(root.ends_with(STORE_SUBDIR));
}
}