1#![allow(unsafe_code)]
4#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used, unused_results))]
5
6pub mod http;
13pub mod local;
14pub mod remote;
15pub mod runtime;
16#[cfg(feature = "s3")]
17pub mod s3;
18pub mod utils;
19
20pub use hexz_core::store::StorageBackend;
21
22use hexz_common::Result;
23use hexz_core::algo::compression::create_compressor;
24use hexz_core::algo::encryption::Encryptor;
25use hexz_core::api::file::{Archive, ParentLoader};
26use hexz_core::format::header::Header;
27use std::sync::Arc;
28
29pub fn open_local(
32 path: &std::path::Path,
33 encryptor: Option<Box<dyn Encryptor>>,
34) -> Result<Arc<Archive>> {
35 open_local_with_cache(path, encryptor, None, None)
36}
37
38pub fn open_local_with_cache(
41 path: &std::path::Path,
42 encryptor: Option<Box<dyn Encryptor>>,
43 cache_capacity_bytes: Option<usize>,
44 prefetch_window_size: Option<u32>,
45) -> Result<Arc<Archive>> {
46 let backend: Arc<dyn StorageBackend> = Arc::new(local::MmapBackend::new(path)?);
47 let header = Header::read_from_backend(backend.as_ref())?;
48 let dictionary = header.load_dictionary(backend.as_ref())?;
49 let compressor = create_compressor(header.compression, None, dictionary.as_deref());
50
51 let archive_dir = path
52 .parent()
53 .unwrap_or_else(|| std::path::Path::new("."))
54 .to_path_buf();
55 let loader: ParentLoader = Box::new(move |parent_path: &str| {
56 let p = std::path::Path::new(parent_path);
57 let full_parent_path = if p.exists() {
58 p.to_path_buf()
59 } else {
60 let rel = archive_dir.join(parent_path);
61 if rel.exists() { rel } else { p.to_path_buf() }
62 };
63 let pb: Arc<dyn StorageBackend> = Arc::new(local::MmapBackend::new(&full_parent_path)?);
64 Archive::open(pb, None)
65 });
66
67 Archive::with_cache_and_loader(
68 backend,
69 compressor,
70 encryptor,
71 cache_capacity_bytes,
72 prefetch_window_size,
73 Some(&loader),
74 )
75}