(body: &[u8])
| 88 | } |
| 89 | |
| 90 | fn decode_structural(body: &[u8]) -> ArrayResult<SparseTile> { |
| 91 | let mut pos = 0; |
| 92 | |
| 93 | if pos + 8 > body.len() { |
| 94 | return Err(ArrayError::SegmentCorruption { |
| 95 | detail: "structural tile: truncated counts".into(), |
| 96 | }); |
| 97 | } |
| 98 | let cell_count = u32::from_le_bytes( |
| 99 | body[pos..pos + 4] |
| 100 | .try_into() |
| 101 | .expect("invariant: bounds-checked above (pos + 8 <= body.len())"), |
| 102 | ) as usize; |
| 103 | pos += 4; |
| 104 | check_decoded_size(cell_count, MAX_CELLS_PER_TILE, "cell_count")?; |
| 105 | let axis_count = u32::from_le_bytes( |
| 106 | body[pos..pos + 4] |
| 107 | .try_into() |
| 108 | .expect("invariant: bounds-checked above (pos + 4 <= body.len())"), |
| 109 | ) as usize; |
| 110 | pos += 4; |
| 111 | check_decoded_size(axis_count, MAX_AXES_PER_TILE, "axis_count")?; |
| 112 | |
| 113 | // Coordinate axes. |
| 114 | let mut dim_dicts = Vec::with_capacity(axis_count); |
| 115 | for _ in 0..axis_count { |
| 116 | let axis_bytes = read_framed(body, &mut pos)?; |
| 117 | let mut inner_pos = 0; |
| 118 | let dict = decode_coord_axis_rle(axis_bytes, &mut inner_pos)?; |
| 119 | dim_dicts.push(dict); |
| 120 | } |
| 121 | |
| 122 | // Surrogates. |
| 123 | let surr_bytes = read_framed(body, &mut pos)?; |
| 124 | let surrogates = decode_surrogates(surr_bytes)?; |
| 125 | |
| 126 | // Row kinds. |
| 127 | let rk_bytes = read_framed(body, &mut pos)?; |
| 128 | let row_kinds = decode_row_kinds(rk_bytes)?; |
| 129 | |
| 130 | // system_from_ms placeholder (not stored in SparseTile, just skip). |
| 131 | let _sys_bytes = read_framed(body, &mut pos)?; |
| 132 | |
| 133 | // valid_from_ms. |
| 134 | let vf_bytes = read_framed(body, &mut pos)?; |
| 135 | let valid_from_ms = decode_timestamps_col(vf_bytes)?; |
| 136 | |
| 137 | // valid_until_ms. |
| 138 | let vu_bytes = read_framed(body, &mut pos)?; |
| 139 | let valid_until_ms = decode_timestamps_col(vu_bytes)?; |
| 140 | |
| 141 | // Attr columns. |
| 142 | if pos + 4 > body.len() { |
| 143 | return Err(ArrayError::SegmentCorruption { |
| 144 | detail: "structural tile: truncated attr count".into(), |
| 145 | }); |
| 146 | } |
| 147 | let attr_count = u32::from_le_bytes( |
no test coverage detected