// Obsidian [[wikilinks]] in doc comments are intentional — they link to
// design and reference docs in docs/. Rustdoc doesn't understand them.
#![allow(rustdoc::broken_intra_doc_links)]

//! `luci-storage` — block-based storage engine for Luci.
//!
//! This crate implements the [[single-file-format]] that backs every Luci
//! index. It manages disk space as fixed-size blocks, tracks free space with
//! extent-based free lists, and provides atomic commit via a two-root-pointer
//! technique.
//!
//! See [[architecture-storage-format]] for the full design.

mod allocator;
mod block;
mod directory;
mod fs_dir;
mod header;
mod single_file;
mod wal;

pub use allocator::BlockAllocator;
pub use block::{BlockId, Extent, BLOCK_SIZE, HEADER_SIZE};
pub use directory::{MetadataSnapshot, SegmentEntry};
pub use fs_dir::FsDirectory;
pub use header::{
    xxh3_checksum, ActiveRoot, FileHeader, RootPointer, FORMAT_VERSION, MAGIC,
};
#[cfg(unix)]
pub use single_file::SingleFileDirectory;
pub use wal::{replay_wal, DurabilityMode, Wal, WalRecord};

use luci_core::{Result, SegmentId};

/// Trait abstracting over storage backends.
///
/// Both [`SingleFileDirectory`] (production, single `.luci` file) and
/// [`FsDirectory`] (debug, one file per segment) implement this interface.
pub trait Storage {
    fn write_segment(&mut self, segment_id: SegmentId, data: &[u8]) -> Result<()>;
    fn read_segment(&self, segment_id: SegmentId) -> Result<Vec<u8>>;
    fn commit(&mut self) -> Result<()>;
    fn segments(&self) -> &[SegmentEntry];
    fn generation(&self) -> u64;
    fn set_user_metadata(&mut self, metadata: Vec<u8>);
    fn user_metadata(&self) -> &[u8];
    /// Mark segments for removal on the next commit. Their storage space
    /// is reclaimed when the commit completes.
    fn remove_segments(&mut self, segment_ids: &[SegmentId]);
}
