Skip to main content

array_format/
block.rs

1//! Block metadata stored in the footer.
2//!
3//! Each block in the data region has a [`BlockMeta`] entry that records
4//! its physical location in the file and compression information.
5
6use std::ops::Range;
7
8use rkyv::{Archive, Deserialize, Serialize};
9
10use crate::address::BlockId;
11
12/// Identifies which compression codec was used for a block.
13///
14/// `None` means the block is stored uncompressed.
15/// [`Named`](CodecId::Named) allows registering custom codecs by string
16/// identifier without modifying this enum.
17#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
18pub enum CodecId {
19    /// No compression applied.
20    None,
21    /// A named compression codec (e.g. `"zstd"`, `"lz4"`).
22    Named(String),
23}
24
25/// Metadata for a single block in the data region.
26///
27/// Stored in the footer's block table. Describes where to find the
28/// block in the file and how to decompress it.
29#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
30pub struct BlockMeta {
31    /// Block identifier.
32    pub id: BlockId,
33    /// Byte offset of the compressed block within the file.
34    pub file_offset: u64,
35    /// Size of the block as stored on disk (compressed).
36    pub compressed_size: u64,
37    /// Size of the block after decompression.
38    pub uncompressed_size: u64,
39    /// Compression codec used for this block.
40    pub codec: CodecId,
41}
42
43impl BlockMeta {
44    /// Returns the byte range within the file that contains this block.
45    pub fn file_range(&self) -> Range<u64> {
46        self.file_offset..self.file_offset + self.compressed_size
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn file_range_computation() {
56        let meta = BlockMeta {
57            id: BlockId(0),
58            file_offset: 100,
59            compressed_size: 50,
60            uncompressed_size: 200,
61            codec: CodecId::None,
62        };
63        assert_eq!(meta.file_range(), 100..150);
64    }
65
66    #[test]
67    fn named_codec_id() {
68        let codec = CodecId::Named("zstd".into());
69        assert_eq!(codec, CodecId::Named("zstd".into()));
70        assert_ne!(codec, CodecId::None);
71    }
72}