kvbm_engine/offload/
source.rs1use std::marker::PhantomData;
12
13use crate::{BlockId, SequenceHash};
14use kvbm_logical::blocks::{BlockMetadata, ImmutableBlock, WeakBlock};
15
16#[derive(Debug, Clone, Copy)]
22pub struct ExternalBlock<T: BlockMetadata> {
23 pub block_id: BlockId,
25 pub sequence_hash: SequenceHash,
27 _marker: PhantomData<T>,
28}
29
30impl<T: BlockMetadata> ExternalBlock<T> {
31 pub fn new(block_id: BlockId, sequence_hash: SequenceHash) -> Self {
33 Self {
34 block_id,
35 sequence_hash,
36 _marker: PhantomData,
37 }
38 }
39}
40
41#[derive(Debug)]
48pub enum SourceBlock<T: BlockMetadata> {
49 External(ExternalBlock<T>),
51 Strong(ImmutableBlock<T>),
53 Weak(WeakBlock<T>),
55}
56
57impl<T: BlockMetadata> SourceBlock<T> {
58 pub fn block_id(&self) -> Option<BlockId> {
63 match self {
64 SourceBlock::External(ext) => Some(ext.block_id),
65 SourceBlock::Strong(block) => Some(block.block_id()),
66 SourceBlock::Weak(_) => None,
67 }
68 }
69
70 pub fn sequence_hash(&self) -> Option<SequenceHash> {
77 match self {
78 SourceBlock::External(ext) => Some(ext.sequence_hash),
79 SourceBlock::Strong(block) => Some(block.sequence_hash()),
80 SourceBlock::Weak(weak) => Some(weak.sequence_hash()),
81 }
82 }
83
84 pub fn is_external(&self) -> bool {
86 matches!(self, SourceBlock::External(_))
87 }
88
89 pub fn is_strong(&self) -> bool {
91 matches!(self, SourceBlock::Strong(_))
92 }
93
94 pub fn is_weak(&self) -> bool {
96 matches!(self, SourceBlock::Weak(_))
97 }
98}
99
100impl<T: BlockMetadata> From<ExternalBlock<T>> for SourceBlock<T> {
101 fn from(ext: ExternalBlock<T>) -> Self {
102 SourceBlock::External(ext)
103 }
104}
105
106impl<T: BlockMetadata> From<ImmutableBlock<T>> for SourceBlock<T> {
107 fn from(block: ImmutableBlock<T>) -> Self {
108 SourceBlock::Strong(block)
109 }
110}
111
112impl<T: BlockMetadata> From<WeakBlock<T>> for SourceBlock<T> {
113 fn from(block: WeakBlock<T>) -> Self {
114 SourceBlock::Weak(block)
115 }
116}
117
118#[derive(Debug)]
123pub enum SourceBlocks<T: BlockMetadata> {
124 External(Vec<ExternalBlock<T>>),
126 Strong(Vec<ImmutableBlock<T>>),
128 Weak(Vec<WeakBlock<T>>),
130}
131
132impl<T: BlockMetadata> SourceBlocks<T> {
133 pub fn empty_external() -> Self {
135 SourceBlocks::External(Vec::new())
136 }
137
138 pub fn empty_strong() -> Self {
140 SourceBlocks::Strong(Vec::new())
141 }
142
143 pub fn empty_weak() -> Self {
145 SourceBlocks::Weak(Vec::new())
146 }
147
148 pub fn len(&self) -> usize {
150 match self {
151 SourceBlocks::External(blocks) => blocks.len(),
152 SourceBlocks::Strong(blocks) => blocks.len(),
153 SourceBlocks::Weak(blocks) => blocks.len(),
154 }
155 }
156
157 pub fn is_empty(&self) -> bool {
159 self.len() == 0
160 }
161
162 pub fn external_blocks(&self) -> Option<&[ExternalBlock<T>]> {
164 match self {
165 SourceBlocks::External(blocks) => Some(blocks),
166 _ => None,
167 }
168 }
169
170 pub fn strong_blocks(&self) -> Option<&[ImmutableBlock<T>]> {
172 match self {
173 SourceBlocks::Strong(blocks) => Some(blocks),
174 _ => None,
175 }
176 }
177
178 pub fn weak_blocks(&self) -> Option<&[WeakBlock<T>]> {
180 match self {
181 SourceBlocks::Weak(blocks) => Some(blocks),
182 _ => None,
183 }
184 }
185
186 pub fn is_external(&self) -> bool {
188 matches!(self, SourceBlocks::External(_))
189 }
190
191 pub fn is_strong(&self) -> bool {
193 matches!(self, SourceBlocks::Strong(_))
194 }
195
196 pub fn is_weak(&self) -> bool {
198 matches!(self, SourceBlocks::Weak(_))
199 }
200}
201
202impl<T: BlockMetadata> From<Vec<ExternalBlock<T>>> for SourceBlocks<T> {
203 fn from(blocks: Vec<ExternalBlock<T>>) -> Self {
204 SourceBlocks::External(blocks)
205 }
206}
207
208impl<T: BlockMetadata> From<Vec<ImmutableBlock<T>>> for SourceBlocks<T> {
209 fn from(blocks: Vec<ImmutableBlock<T>>) -> Self {
210 SourceBlocks::Strong(blocks)
211 }
212}
213
214impl<T: BlockMetadata> From<Vec<WeakBlock<T>>> for SourceBlocks<T> {
215 fn from(blocks: Vec<WeakBlock<T>>) -> Self {
216 SourceBlocks::Weak(blocks)
217 }
218}
219
220impl<T: BlockMetadata> From<SourceBlock<T>> for SourceBlocks<T> {
222 fn from(block: SourceBlock<T>) -> Self {
223 match block {
224 SourceBlock::External(ext) => SourceBlocks::External(vec![ext]),
225 SourceBlock::Strong(b) => SourceBlocks::Strong(vec![b]),
226 SourceBlock::Weak(b) => SourceBlocks::Weak(vec![b]),
227 }
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use kvbm_common::tokens::TokenBlockSequence;
235 use kvbm_logical::KvbmSequenceHashProvider;
236
237 fn test_seq_hash(position: usize) -> SequenceHash {
239 let tokens_per_block = 4;
240 let total_tokens = (position + 1) * tokens_per_block;
241 let tokens: Vec<u32> = (0..total_tokens as u32).collect();
242 let seq = TokenBlockSequence::from_slice(&tokens, tokens_per_block as u32, Some(1337));
243 seq.blocks()[position].kvbm_sequence_hash()
244 }
245
246 #[test]
247 fn test_external_block_creation() {
248 let hash = test_seq_hash(0);
249 let ext: ExternalBlock<()> = ExternalBlock::new(42, hash);
250 assert_eq!(ext.block_id, 42);
251 assert_eq!(ext.sequence_hash, hash);
252 }
253
254 #[test]
255 fn test_source_blocks_from_vec_external() {
256 let ext1: ExternalBlock<()> = ExternalBlock::new(1, test_seq_hash(0));
257 let ext2: ExternalBlock<()> = ExternalBlock::new(2, test_seq_hash(1));
258 let ext3: ExternalBlock<()> = ExternalBlock::new(3, test_seq_hash(2));
259 let blocks: SourceBlocks<()> = vec![ext1, ext2, ext3].into();
260 assert!(blocks.is_external());
261 assert_eq!(blocks.len(), 3);
262 let external = blocks.external_blocks().unwrap();
263 assert_eq!(external[0].block_id, 1);
264 assert_eq!(external[1].block_id, 2);
265 assert_eq!(external[2].block_id, 3);
266 }
267
268 #[test]
269 fn test_source_blocks_empty() {
270 let blocks: SourceBlocks<()> = SourceBlocks::empty_external();
271 assert!(blocks.is_empty());
272 assert!(blocks.is_external());
273 }
274
275 #[test]
276 fn test_source_block_accessors() {
277 let hash = test_seq_hash(5);
278 let ext: ExternalBlock<()> = ExternalBlock::new(42, hash);
279 let block: SourceBlock<()> = ext.into();
280 assert_eq!(block.block_id(), Some(42));
281 assert_eq!(block.sequence_hash(), Some(hash));
282 assert!(block.is_external());
283 }
284}