Iterate every row in a [`SparseTile`], decoding coords and payload. Rows are returned in storage order (same as `row_count()` iteration). Attribute columns in `SparseTile` are indexed by *live-row index*, not by iteration index, so a separate live counter advances only for Live rows.
(tile: &SparseTile)
| 69 | /// Attribute columns in `SparseTile` are indexed by *live-row index*, not by |
| 70 | /// iteration index, so a separate live counter advances only for Live rows. |
| 71 | pub fn decode_sparse_rows(tile: &SparseTile) -> ArrayResult<Vec<DecodedRow>> { |
| 72 | let n = tile.row_count(); |
| 73 | let arity = tile.dim_dicts.len(); |
| 74 | let mut rows = Vec::with_capacity(n); |
| 75 | let mut live_idx: usize = 0; |
| 76 | |
| 77 | for row in 0..n { |
| 78 | // Decode coordinate for this row. |
| 79 | let mut coord = Vec::with_capacity(arity); |
| 80 | for dim_idx in 0..arity { |
| 81 | let dict = |
| 82 | tile.dim_dicts |
| 83 | .get(dim_idx) |
| 84 | .ok_or_else(|| ArrayError::SegmentCorruption { |
| 85 | detail: format!("decode_sparse_rows: dim {dim_idx} missing"), |
| 86 | })?; |
| 87 | let entry_idx = *dict |
| 88 | .indices |
| 89 | .get(row) |
| 90 | .ok_or_else(|| ArrayError::SegmentCorruption { |
| 91 | detail: format!("decode_sparse_rows: row {row} index out of range"), |
| 92 | })? as usize; |
| 93 | let val = dict |
| 94 | .values |
| 95 | .get(entry_idx) |
| 96 | .ok_or_else(|| ArrayError::SegmentCorruption { |
| 97 | detail: format!("decode_sparse_rows: dict entry {entry_idx} out of range"), |
| 98 | })?; |
| 99 | coord.push(val.clone()); |
| 100 | } |
| 101 | |
| 102 | let coord_key = encode_coord_key(&coord)?; |
| 103 | let kind = tile.row_kind(row)?; |
| 104 | |
| 105 | let payload = match kind { |
| 106 | RowKind::Live => { |
| 107 | // Build attrs from each attr column using live_idx. |
| 108 | let attrs: Vec<_> = tile |
| 109 | .attr_cols |
| 110 | .iter() |
| 111 | .map(|col| { |
| 112 | col.get(live_idx) |
| 113 | .cloned() |
| 114 | .ok_or_else(|| ArrayError::SegmentCorruption { |
| 115 | detail: format!( |
| 116 | "decode_sparse_rows: attr col live_idx {live_idx} out of range" |
| 117 | ), |
| 118 | }) |
| 119 | }) |
| 120 | .collect::<ArrayResult<Vec<_>>>()?; |
| 121 | |
| 122 | let surrogate = tile.surrogates.get(row).copied().unwrap_or(Surrogate::ZERO); |
| 123 | let valid_from_ms = tile.valid_from_ms.get(row).copied().ok_or_else(|| { |
| 124 | ArrayError::SegmentCorruption { |
| 125 | detail: format!("decode_sparse_rows: valid_from_ms row {row} out of range"), |
| 126 | } |
| 127 | })?; |
| 128 | let valid_until_ms = tile.valid_until_ms.get(row).copied().ok_or_else(|| { |
no test coverage detected