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