Decode FSST-compressed data back to strings.
(data: &[u8])
| 194 | |
| 195 | /// Decode FSST-compressed data back to strings. |
| 196 | pub fn decode(data: &[u8]) -> Result<Vec<Vec<u8>>, CodecError> { |
| 197 | if data.len() < 2 { |
| 198 | return Err(CodecError::Truncated { |
| 199 | expected: 2, |
| 200 | actual: data.len(), |
| 201 | }); |
| 202 | } |
| 203 | |
| 204 | // Read symbol table. |
| 205 | let sym_count = u16::from_le_bytes([data[0], data[1]]) as usize; |
| 206 | let mut pos = 2; |
| 207 | let mut symbols: Vec<Vec<u8>> = Vec::with_capacity(sym_count); |
| 208 | |
| 209 | for _ in 0..sym_count { |
| 210 | if pos >= data.len() { |
| 211 | return Err(CodecError::Truncated { |
| 212 | expected: pos + 1, |
| 213 | actual: data.len(), |
| 214 | }); |
| 215 | } |
| 216 | let len = data[pos] as usize; |
| 217 | pos += 1; |
| 218 | if pos + len > data.len() { |
| 219 | return Err(CodecError::Truncated { |
| 220 | expected: pos + len, |
| 221 | actual: data.len(), |
| 222 | }); |
| 223 | } |
| 224 | symbols.push(data[pos..pos + len].to_vec()); |
| 225 | pos += len; |
| 226 | } |
| 227 | |
| 228 | // Read header. |
| 229 | if pos + 8 > data.len() { |
| 230 | return Err(CodecError::Truncated { |
| 231 | expected: pos + 8, |
| 232 | actual: data.len(), |
| 233 | }); |
| 234 | } |
| 235 | let _total_encoded = |
| 236 | u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]) as usize; |
| 237 | pos += 4; |
| 238 | let string_count = |
| 239 | u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]) as usize; |
| 240 | pos += 4; |
| 241 | |
| 242 | // Read offsets. |
| 243 | let offsets_size = string_count * 4; |
| 244 | if pos + offsets_size > data.len() { |
| 245 | return Err(CodecError::Truncated { |
| 246 | expected: pos + offsets_size, |
| 247 | actual: data.len(), |
| 248 | }); |
| 249 | } |
| 250 | let mut offsets = Vec::with_capacity(string_count); |
| 251 | for i in 0..string_count { |
| 252 | let off_pos = pos + i * 4; |
| 253 | offsets.push(u32::from_le_bytes([ |