nodedb_array/tile/
dense_tile.rs1use serde::{Deserialize, Serialize};
11
12use super::mbr::TileMBR;
13use crate::schema::ArraySchema;
14use crate::types::cell_value::value::CellValue;
15
16#[derive(
18 Debug,
19 Clone,
20 PartialEq,
21 Serialize,
22 Deserialize,
23 zerompk::ToMessagePack,
24 zerompk::FromMessagePack,
25)]
26pub struct DenseTile {
27 pub attr_cols: Vec<Vec<CellValue>>,
31 pub tile_extents: Vec<u64>,
34 pub mbr: TileMBR,
35}
36
37impl DenseTile {
38 pub fn empty(schema: &ArraySchema) -> Self {
41 let cells = cells_per_tile(&schema.tile_extents);
42 Self {
43 attr_cols: (0..schema.attrs.len())
44 .map(|_| vec![CellValue::Null; cells])
45 .collect(),
46 tile_extents: schema.tile_extents.clone(),
47 mbr: TileMBR::new(schema.arity(), schema.attrs.len()),
48 }
49 }
50
51 pub fn cell_count(&self) -> usize {
52 cells_per_tile(&self.tile_extents)
53 }
54
55 pub fn cell(&self, attr_idx: usize, i: usize) -> Option<&CellValue> {
57 self.attr_cols.get(attr_idx).and_then(|c| c.get(i))
58 }
59}
60
61pub fn cells_per_tile(extents: &[u64]) -> usize {
63 let mut p: u128 = 1;
64 for e in extents {
65 p = p.saturating_mul(*e as u128);
66 }
67 if p > usize::MAX as u128 {
68 usize::MAX
69 } else {
70 p as usize
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::schema::ArraySchemaBuilder;
78 use crate::schema::attr_spec::{AttrSpec, AttrType};
79 use crate::schema::dim_spec::{DimSpec, DimType};
80 use crate::types::domain::{Domain, DomainBound};
81
82 fn schema_4x4() -> ArraySchema {
83 ArraySchemaBuilder::new("g")
84 .dim(DimSpec::new(
85 "x",
86 DimType::Int64,
87 Domain::new(DomainBound::Int64(0), DomainBound::Int64(3)),
88 ))
89 .dim(DimSpec::new(
90 "y",
91 DimType::Int64,
92 Domain::new(DomainBound::Int64(0), DomainBound::Int64(3)),
93 ))
94 .attr(AttrSpec::new("v", AttrType::Int64, true))
95 .tile_extents(vec![4, 4])
96 .build()
97 .unwrap()
98 }
99
100 #[test]
101 fn cells_per_tile_is_product_of_extents() {
102 assert_eq!(cells_per_tile(&[4, 4]), 16);
103 assert_eq!(cells_per_tile(&[2, 3, 5]), 30);
104 assert_eq!(cells_per_tile(&[1]), 1);
105 }
106
107 #[test]
108 fn dense_tile_starts_all_null() {
109 let s = schema_4x4();
110 let t = DenseTile::empty(&s);
111 assert_eq!(t.cell_count(), 16);
112 for col in &t.attr_cols {
113 assert!(col.iter().all(|c| matches!(c, CellValue::Null)));
114 }
115 }
116}