nodedb_array/schema/
builder.rs1use super::array_schema::ArraySchema;
11use super::attr_spec::AttrSpec;
12use super::cell_order::{CellOrder, TileOrder};
13use super::dim_spec::DimSpec;
14use super::validation;
15use crate::error::ArrayResult;
16
17#[derive(Debug, Clone)]
19pub struct ArraySchemaBuilder {
20 name: String,
21 dims: Vec<DimSpec>,
22 attrs: Vec<AttrSpec>,
23 tile_extents: Vec<u64>,
24 cell_order: CellOrder,
25 tile_order: TileOrder,
26}
27
28impl ArraySchemaBuilder {
29 pub fn new(name: impl Into<String>) -> Self {
30 Self {
31 name: name.into(),
32 dims: Vec::new(),
33 attrs: Vec::new(),
34 tile_extents: Vec::new(),
35 cell_order: CellOrder::default(),
36 tile_order: TileOrder::default(),
37 }
38 }
39
40 pub fn dim(mut self, dim: DimSpec) -> Self {
41 self.dims.push(dim);
42 self
43 }
44
45 pub fn attr(mut self, attr: AttrSpec) -> Self {
46 self.attrs.push(attr);
47 self
48 }
49
50 pub fn tile_extents(mut self, extents: Vec<u64>) -> Self {
51 self.tile_extents = extents;
52 self
53 }
54
55 pub fn cell_order(mut self, order: CellOrder) -> Self {
56 self.cell_order = order;
57 self
58 }
59
60 pub fn tile_order(mut self, order: TileOrder) -> Self {
61 self.tile_order = order;
62 self
63 }
64
65 pub fn build(self) -> ArrayResult<ArraySchema> {
66 validation::dims::check(&self.name, &self.dims)?;
67 validation::attrs::check(&self.name, &self.attrs)?;
68 validation::tiles::check(&self.name, &self.dims, &self.tile_extents)?;
69 Ok(ArraySchema {
70 name: self.name,
71 dims: self.dims,
72 attrs: self.attrs,
73 tile_extents: self.tile_extents,
74 cell_order: self.cell_order,
75 tile_order: self.tile_order,
76 })
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::super::attr_spec::AttrType;
83 use super::super::dim_spec::DimType;
84 use super::*;
85 use crate::types::domain::{Domain, DomainBound};
86
87 fn int64_dim(name: &str, hi: i64) -> DimSpec {
88 DimSpec::new(
89 name,
90 DimType::Int64,
91 Domain::new(DomainBound::Int64(0), DomainBound::Int64(hi)),
92 )
93 }
94
95 #[test]
96 fn build_succeeds_for_well_formed_schema() {
97 let s = ArraySchemaBuilder::new("g")
98 .dim(int64_dim("chrom", 24))
99 .dim(int64_dim("pos", 300_000_000))
100 .attr(AttrSpec::new("variant", AttrType::String, false))
101 .tile_extents(vec![1, 1_000_000])
102 .build()
103 .unwrap();
104 assert_eq!(s.arity(), 2);
105 assert_eq!(s.cell_order, CellOrder::Hilbert);
106 }
107
108 #[test]
109 fn build_rejects_no_dims() {
110 let r = ArraySchemaBuilder::new("g")
111 .attr(AttrSpec::new("v", AttrType::Int64, false))
112 .tile_extents(vec![])
113 .build();
114 assert!(r.is_err());
115 }
116
117 #[test]
118 fn build_rejects_no_attrs() {
119 let r = ArraySchemaBuilder::new("g")
120 .dim(int64_dim("d", 10))
121 .tile_extents(vec![1])
122 .build();
123 assert!(r.is_err());
124 }
125
126 #[test]
127 fn build_rejects_extent_arity_mismatch() {
128 let r = ArraySchemaBuilder::new("g")
129 .dim(int64_dim("d", 10))
130 .attr(AttrSpec::new("v", AttrType::Int64, false))
131 .tile_extents(vec![1, 2])
132 .build();
133 assert!(r.is_err());
134 }
135}