1pub const HEADER_SIZE: u32 = 4096;
9
10pub const BLOCK_SIZE: u32 = 256 * 1024;
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
27pub struct BlockId(pub u64);
28
29impl BlockId {
30 pub const fn new(id: u64) -> Self {
31 Self(id)
32 }
33
34 pub const fn as_u64(self) -> u64 {
35 self.0
36 }
37
38 pub const fn byte_offset(self) -> u64 {
42 HEADER_SIZE as u64 + self.0 * BLOCK_SIZE as u64
43 }
44}
45
46impl std::fmt::Display for BlockId {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 write!(f, "block:{}", self.0)
49 }
50}
51
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
59pub struct Extent {
60 pub start: BlockId,
62 pub count: u32,
64}
65
66impl Extent {
67 pub const fn new(start: BlockId, count: u32) -> Self {
68 Self { start, count }
69 }
70
71 pub const fn end(&self) -> BlockId {
73 BlockId(self.start.0 + self.count as u64)
74 }
75
76 pub const fn byte_len(&self) -> u64 {
78 self.count as u64 * BLOCK_SIZE as u64
79 }
80
81 pub const fn is_adjacent_to(&self, other: &Extent) -> bool {
83 self.end().0 == other.start.0
84 }
85}
86
87impl std::fmt::Display for Extent {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 write!(
90 f,
91 "blocks:[{}..{})",
92 self.start.0,
93 self.start.0 + self.count as u64
94 )
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn block_id_byte_offset() {
104 assert_eq!(BlockId(0).byte_offset(), 4096);
106 assert_eq!(BlockId(1).byte_offset(), 4096 + 256 * 1024);
107 assert_eq!(BlockId(4).byte_offset(), 4096 + 4 * 256 * 1024);
108 }
109
110 #[test]
111 fn block_id_display() {
112 assert_eq!(format!("{}", BlockId(42)), "block:42");
113 }
114
115 #[test]
116 fn extent_end() {
117 let ext = Extent::new(BlockId(10), 5);
118 assert_eq!(ext.end(), BlockId(15));
119 }
120
121 #[test]
122 fn extent_byte_len() {
123 let ext = Extent::new(BlockId(0), 4);
124 assert_eq!(ext.byte_len(), 4 * 256 * 1024);
125 }
126
127 #[test]
128 fn extent_adjacency() {
129 let a = Extent::new(BlockId(10), 5);
130 let b = Extent::new(BlockId(15), 3);
131 let c = Extent::new(BlockId(20), 2);
132 assert!(a.is_adjacent_to(&b));
133 assert!(!a.is_adjacent_to(&c));
134 assert!(b.is_adjacent_to(&Extent::new(BlockId(18), 2)));
135 assert!(!b.is_adjacent_to(&c));
136 }
137
138 #[test]
139 fn extent_display() {
140 let ext = Extent::new(BlockId(3), 7);
141 assert_eq!(format!("{ext}"), "blocks:[3..10)");
142 }
143
144 #[test]
145 fn block_size_is_256kb() {
146 assert_eq!(BLOCK_SIZE, 262_144);
147 }
148
149 #[test]
150 fn header_size_is_4kb() {
151 assert_eq!(HEADER_SIZE, 4096);
152 }
153}