Skip to main content

hexz_store/
lib.rs

1// unsafe required for: mmap-based file I/O and pread(2) syscalls.
2// All unsafe blocks have individual SAFETY comments.
3#![allow(unsafe_code)]
4#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used, unused_results))]
5
6//! Storage backend implementations for Hexz archives.
7//!
8//! This crate provides concrete implementations of `hexz_core::store::StorageBackend`
9//! for local files, HTTP/HTTPS, and S3-compatible object storage. It also exposes a
10//! `ParentLoader` helper for opening thin-archive parent chains via `ArchiveBackend`.
11
12pub 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
29/// Opens a Hexz archive from a local file path, resolving any parent chain via
30/// `ArchiveBackend`. This is the standard entry point when working with local archives.
31pub 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
38/// Like [`open_local`] but with custom cache and prefetch settings.
39/// Like [`open_local`] but with custom cache and prefetch settings.
40pub 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}