dwarfs 0.1.0

A library for reading DwarFS archives (aka. DwarFS images)
Documentation
//! A library for reading [DwarFS][dwarfs] archives (aka. images).
//!
//! Currently, DwarFS filesystem version 2.3..=2.5 is supported,
//! which should be compatible with files generated by
//! [upstream `mkdwarfs`][dwarfs] v0.5.0..=v0.12.4 (latest at the time of
//! writing). Other versions may also be readable but are not guaranteed.
//!
//! [dwarfs]: https://github.com/mhx/dwarfs
//!
//! ```
//! use dwarfs::{Archive, ArchiveIndex, AsChunks};
//! use std::fs::File;
//!
//! # fn wrap() -> dwarfs::Result<()> {
//! // Open an archive file and load the metadata of it.
//! let file = File::open("./my.dwarfs")?;
//! let (index, mut archive) = Archive::new(file)?;
//!
//! // Hierarchy traversal.
//! for entry in index.root().entries() {
//!     let inode = entry.inode();
//!     println!("/{} mode={}", entry.name(), inode.metadata().file_type_mode());
//!     if let Some(deep) = inode.as_dir() {
//!         for entry in deep.entries() {
//!             // ...
//!         }
//!     }
//! }
//!
//! // Resolve paths.
//! let file: dwarfs::File = index.get_path(["src", "Cargo.toml"])
//!     .expect("does not exist")
//!     .as_file()
//!     .expect("not a file");
//! // The simple way to read content.
//! let bytes: Vec<u8> = file.read_to_vec(&mut archive)?;
//!
//! # Ok(()) }
//! ```
//!
//! ## Cargo features
//!
//! - `zstd`, `lzma`, `lz4` *(Only `zstd` is enabled by default)*
//!
//!   Enable relevant decompression algorithm support. `zstd` is the default
//!   compression algorithm `mkdwarfs` uses and it should be enough for most cases.
//!
//! - `log` *(Enabled by default)*
//!
//!   Enable trace-level logging and time measurement for internal events via
//!   [`log` crate][log]. Useful for profiling or debugging. Should not
//!   have performance penalty unless trace-level log is enabled.
//!
//! [log]: https://crates.io/crates/log
#![forbid(unsafe_code)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]

#[cfg(feature = "log")]
#[macro_use(trace_time)]
extern crate measure_time;

#[cfg(feature = "log")]
#[macro_use(trace)]
extern crate log;

#[cfg(not(feature = "log"))]
#[macro_use]
mod macros {
    macro_rules! trace {
        ($($tt:tt)*) => {
            let _ = if false {
                let _ = ::std::format_args!($($tt)*);
            };
        };
    }

    macro_rules! trace_time {
        ($($tt:tt)*) => {
            trace!($($tt)*)
        };
    }
}

macro_rules! bail {
    ($err:expr $(,)?) => {
        return Err(Into::into($err))
    };
}

pub mod archive;
pub mod fsst;
pub mod metadata;
pub mod section;

pub extern crate positioned_io;

/// The range of filesystem version tuple `(major, minor)` supported by this library.
///
/// Currently this is `(2, 3)..=(2, 5)`.
// TODO: We could lower this.
pub const SUPPORTED_VERSION_RANGE: std::ops::RangeInclusive<(u8, u8)> = (2, 3)..=(2, 5);

use std::{cmp::Ordering, ops::Range};

#[doc(inline)]
pub use archive::{
    Archive, ArchiveIndex, AsChunks, Device, Dir, DirEntry, Error, File, Inode, InodeKind,
    InodeMetadata, Ipc, Result, Symlink,
};

/// There is currently no binary search functions in std over a generic range.
/// This is copied from std: <https://github.com/rust-lang/rust/blob/1.86.0/library/core/src/slice/mod.rs#L2817>
/// License: MIT OR Apache-2.0
fn bisect_range_by<F>(range: Range<usize>, mut f: F) -> Option<usize>
where
    F: FnMut(usize) -> Ordering,
{
    let total_size = range.end - range.start;
    let mut size = total_size;
    if size == 0 {
        return None;
    }
    let mut base = 0usize;

    while size > 1 {
        let half = size / 2;
        let mid = base + half;
        let cmp = f(mid);
        // WAIT: Rust 1.88
        // base = (cmp == Ordering::Greater).select_unpredictable(base, mid);
        base = if cmp == Ordering::Greater { base } else { mid };
        size -= half;
    }

    let cmp = f(base);
    if cmp == Ordering::Equal {
        debug_assert!(base < total_size);
        Some(base)
    } else {
        None
    }
}