| 154 | } |
| 155 | |
| 156 | pub fn decode_attr_col(data: &[u8]) -> ArrayResult<Vec<CellValue>> { |
| 157 | if data.is_empty() { |
| 158 | return Err(ArrayError::SegmentCorruption { |
| 159 | detail: "attr col: empty payload".into(), |
| 160 | }); |
| 161 | } |
| 162 | let tag = data[0]; |
| 163 | let body = &data[1..]; |
| 164 | |
| 165 | match tag { |
| 166 | ATTR_TAG_INT64 => { |
| 167 | let ints = nodedb_codec::fastlanes::decode(body).map_err(codec_err)?; |
| 168 | Ok(ints.into_iter().map(CellValue::Int64).collect()) |
| 169 | } |
| 170 | ATTR_TAG_FLOAT64 => { |
| 171 | let floats = nodedb_codec::gorilla::decode_f64(body).map_err(codec_err)?; |
| 172 | Ok(floats.into_iter().map(CellValue::Float64).collect()) |
| 173 | } |
| 174 | ATTR_TAG_MSGPACK => { |
| 175 | if body.len() < 4 { |
| 176 | return Err(ArrayError::SegmentCorruption { |
| 177 | detail: "attr col msgpack: truncated count".into(), |
| 178 | }); |
| 179 | } |
| 180 | let count = u32::from_le_bytes( |
| 181 | body[0..4] |
| 182 | .try_into() |
| 183 | .expect("invariant: bounds-checked above (body.len() >= 4)"), |
| 184 | ) as usize; |
| 185 | check_decoded_size(count, MAX_COLUMN_ENTRIES, "attr_col_msgpack count")?; |
| 186 | let mut pos = 4; |
| 187 | let mut values = Vec::with_capacity(count); |
| 188 | for _ in 0..count { |
| 189 | if pos + 4 > body.len() { |
| 190 | return Err(ArrayError::SegmentCorruption { |
| 191 | detail: "attr col msgpack: truncated entry len".into(), |
| 192 | }); |
| 193 | } |
| 194 | let len = u32::from_le_bytes( |
| 195 | body[pos..pos + 4] |
| 196 | .try_into() |
| 197 | .expect("invariant: bounds-checked above (pos + 4 <= body.len())"), |
| 198 | ) as usize; |
| 199 | pos += 4; |
| 200 | if pos + len > body.len() { |
| 201 | return Err(ArrayError::SegmentCorruption { |
| 202 | detail: "attr col msgpack: truncated entry bytes".into(), |
| 203 | }); |
| 204 | } |
| 205 | let v: CellValue = zerompk::from_msgpack(&body[pos..pos + len]).map_err(|e| { |
| 206 | ArrayError::SegmentCorruption { |
| 207 | detail: format!("attr col decode: {e}"), |
| 208 | } |
| 209 | })?; |
| 210 | pos += len; |
| 211 | values.push(v); |
| 212 | } |
| 213 | Ok(values) |