ifc_lite_core/
dense_index.rs1use std::sync::Arc;
8use crate::{columnar_index::EntityIndexStore, EntityDecoder};
9
10pub struct DenseEntityIndex {
15 starts: Vec<u32>,
16 lengths: Vec<u32>,
17 present: Vec<u64>,
18 grid_axis_index: Arc<crate::decoder::GridAxisIndex>,
19}
20
21impl DenseEntityIndex {
22 pub fn try_from_columns(ids: &[u32], starts: &[u32], lengths: &[u32]) -> Option<Self> {
27 if ids.is_empty() || starts.len() != ids.len() || lengths.len() != ids.len()
28 || !ids.windows(2).all(|pair| pair[0] < pair[1]) {
29 return None;
30 }
31 let slots = u64::from(*ids.last()?) + 1;
32 let words = slots.div_ceil(64);
33 if slots * 8 + words * 8 > ids.len() as u64 * 12 { return None; }
34 let slots = usize::try_from(slots).ok()?;
35 let mut index = Self {
36 starts: vec![0; slots], lengths: vec![0; slots],
37 present: vec![0; usize::try_from(words).ok()?],
38 grid_axis_index: Arc::default(),
39 };
40 for (i, &id) in ids.iter().enumerate() {
41 let slot = id as usize;
42 index.starts[slot] = starts[i];
43 index.lengths[slot] = lengths[i];
44 index.present[slot / 64] |= 1u64 << (slot % 64);
45 }
46 Some(index)
47 }
48
49 #[inline]
51 pub fn lookup(&self, id: u32) -> Option<(usize, usize)> {
52 let slot = id as usize;
53 let start = *self.starts.get(slot)? as usize;
54 if self.present[slot / 64] & (1u64 << (slot % 64)) == 0 { return None; }
55 Some((start, start.saturating_add(self.lengths[slot] as usize)))
56 }
57}
58
59impl EntityDecoder<'_> {
60 pub fn set_dense_index(&mut self, index: Arc<DenseEntityIndex>) {
63 self.set_grid_axis_index(index.grid_axis_index.clone());
64 self.entity_index = Some(EntityIndexStore::Dense(index));
65 }
66}
67
68#[cfg(test)]
69#[path = "dense_index_tests.rs"]
70mod tests;