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}