Skip to main content

array_format/
address.rs

1//! Block identifiers and chunk address types.
2//!
3//! A [`ChunkAddress`] locates a slice of array data within a specific
4//! block by `(block_id, offset, size)`.
5
6use rkyv::{Archive, Deserialize, Serialize};
7
8/// A block-relative allocation: which block, and the byte range within it.
9///
10/// The write-side counterpart of [`ChunkAddress`], using `u64` offsets/sizes
11/// while a layer is being built; it narrows to [`ChunkAddress`] on flush.
12#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Archive, Serialize, Deserialize)]
13pub(crate) struct BlockAllocAddress {
14    id: BlockId,
15    offset: u64,
16    size: u64,
17}
18
19/// A block identifier within the file.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Archive, Serialize, Deserialize)]
21pub struct BlockId(pub u32);
22
23/// Locates a contiguous slice of bytes within a block.
24///
25/// To read the data: find the block identified by [`block_id`](ChunkAddress::block_id),
26/// seek to [`offset`](ChunkAddress::offset) bytes into the decompressed block,
27/// and read [`size`](ChunkAddress::size) bytes.
28#[derive(Debug, Clone, PartialEq, Archive, Serialize, Deserialize)]
29pub struct ChunkAddress {
30    /// Which block the data resides in.
31    pub block_id: BlockId,
32    /// Byte offset within the decompressed block.
33    pub offset: u32,
34    /// Number of bytes to read from the block.
35    pub size: u32,
36}
37
38impl BlockAllocAddress {
39    /// Creates an address for `size` bytes at `offset` within block `id`.
40    pub(crate) fn new(id: BlockId, offset: u64, size: u64) -> Self {
41        Self { id, offset, size }
42    }
43
44    /// The block this allocation lives in.
45    pub(crate) fn id(&self) -> BlockId {
46        self.id
47    }
48
49    /// Byte offset of the allocation within the block.
50    pub(crate) fn offset(&self) -> u64 {
51        self.offset
52    }
53
54    /// Length of the allocation in bytes.
55    pub(crate) fn size(&self) -> u64 {
56        self.size
57    }
58}
59
60impl From<BlockAllocAddress> for ChunkAddress {
61    fn from(a: BlockAllocAddress) -> Self {
62        ChunkAddress {
63            block_id: a.id,
64            offset: a.offset as u32,
65            size: a.size as u32,
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn block_id_copy() {
76        let a = BlockId(7);
77        let b = a;
78        assert_eq!(a, b);
79    }
80
81    #[test]
82    fn chunk_address_fields() {
83        let addr = ChunkAddress {
84            block_id: BlockId(3),
85            offset: 1024,
86            size: 4096,
87        };
88        assert_eq!(addr.block_id, BlockId(3));
89        assert_eq!(addr.offset, 1024);
90        assert_eq!(addr.size, 4096);
91    }
92}