Skip to main content

array_format/
block.rs

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