micromegas_object_cache/
blocks.rs1use bytes::Bytes;
2use std::ops::Range;
3
4pub fn blocks_for_range(start: u64, end: u64, block_size: u64) -> Range<u64> {
5 debug_assert!(start < end);
6 let first = start / block_size;
7 let last = (end - 1) / block_size;
8 first..last + 1
9}
10
11pub fn block_byte_range(block_idx: u64, block_size: u64, file_size: u64) -> Range<u64> {
12 let start = block_idx * block_size;
13 let end = (start + block_size).min(file_size);
14 start..end
15}
16
17pub fn coalesce_runs(
22 sorted_missing_owned: &[u64],
23 block_size: u64,
24 max_coalesced_get_bytes: u64,
25) -> Vec<Range<u64>> {
26 let max_blocks_per_run = (max_coalesced_get_bytes / block_size).max(1);
27 let mut runs = Vec::new();
28 let mut i = 0;
29 while i < sorted_missing_owned.len() {
30 let mut j = i;
31 while j + 1 < sorted_missing_owned.len()
32 && sorted_missing_owned[j + 1] == sorted_missing_owned[j] + 1
33 && sorted_missing_owned[j + 1] - sorted_missing_owned[i] < max_blocks_per_run
34 {
35 j += 1;
36 }
37 runs.push(sorted_missing_owned[i]..sorted_missing_owned[j] + 1);
38 i = j + 1;
39 }
40 runs
41}
42
43pub fn assemble_range(
44 blocks: &[(u64, Bytes)],
45 block_size: u64,
46 req_start: u64,
47 req_end: u64,
48) -> Bytes {
49 if req_start >= req_end || blocks.is_empty() {
50 return Bytes::new();
51 }
52 let mut result = Vec::with_capacity((req_end - req_start) as usize);
53 for (block_idx, block_data) in blocks {
54 let blk_start = block_idx * block_size;
55 let blk_end = blk_start + block_data.len() as u64;
56 let clip_start = req_start.max(blk_start);
57 let clip_end = req_end.min(blk_end);
58 if clip_start < clip_end {
59 let local_start = (clip_start - blk_start) as usize;
60 let local_end = (clip_end - blk_start) as usize;
61 result.extend_from_slice(&block_data[local_start..local_end]);
62 }
63 }
64 Bytes::from(result)
65}