use alloc::string::{String, ToString};
use super::ARCHIVE_CACHE;
use super::types::{ArchiveError, ArchiveType};
pub fn resolve_archive_path(path: &str) -> Option<ResolvedPath> {
let components: alloc::vec::Vec<&str> = path.split('/').collect();
for i in 1..components.len() {
let potential_archive = components[..i].join("/");
if let Some(archive_type) = super::detect_archive_type(&potential_archive) {
let inner_path = components[i..].join("/");
return Some(ResolvedPath::InArchive {
archive_path: potential_archive,
archive_type,
inner_path,
});
}
}
None
}
#[derive(Debug, Clone)]
pub enum ResolvedPath {
Normal(String),
InArchive {
archive_path: String,
archive_type: ArchiveType,
inner_path: String,
},
}
pub fn get_or_open_archive(path: &str) -> Result<super::types::ArchiveMount, ArchiveError> {
{
let cache = ARCHIVE_CACHE.lock();
if let Some(mount) = cache.get(path) {
return Ok(mount.clone());
}
}
let mount = super::types::ArchiveMount::open(path)?;
{
let mut cache = ARCHIVE_CACHE.lock();
cache.insert(path.to_string(), mount.clone());
}
Ok(mount)
}
pub fn evict_archive(path: &str) {
let mut cache = ARCHIVE_CACHE.lock();
cache.remove(path);
}
pub fn clear_archive_cache() {
let mut cache = ARCHIVE_CACHE.lock();
cache.clear();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_resolve_normal_path() {
assert!(resolve_archive_path("/data/file.txt").is_none());
}
#[test]
fn test_resolve_archive_path() {
let resolved = resolve_archive_path("/data/archive.zip/inner/file.txt");
assert!(resolved.is_some());
if let Some(ResolvedPath::InArchive {
archive_path,
inner_path,
..
}) = resolved
{
assert_eq!(archive_path, "/data/archive.zip");
assert_eq!(inner_path, "inner/file.txt");
}
}
}