harden obiskio error handling with explicit variants and bounds checking

Extend `SKError` with `BadMagic`, `Truncated`, and `InvalidData` variants to replace `expect()` calls and unsafe slice indexing. Implement proper error chaining via `source()` and update `Display` formatting. Improve magic byte validation and serde error mapping for clearer debugging. Documents a broader roadmap for further crate hardening, including LRU eviction, concurrency, and benchmarking.
This commit is contained in:
Eric Coissac
2026-05-09 18:26:08 +08:00
parent 5169f65dc9
commit e008a8beb4
4 changed files with 126 additions and 11 deletions
+16 -8
View File
@@ -218,23 +218,31 @@ fn read_idx(path: &Path) -> SKResult<(Vec<u8>, Vec<u32>)> {
let data = std::fs::read(path).map_err(SKError::Io)?;
let mut pos = 0;
if &data[pos..pos + 4] != &MAGIC {
return Err(SKError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"unitig index: bad magic",
)));
let magic_bytes = data.get(pos..pos + 4)
.ok_or(SKError::Truncated { context: "unitig index: magic" })?;
if magic_bytes != &MAGIC {
return Err(SKError::BadMagic {
expected: "UIDX",
got: magic_bytes.try_into().unwrap(),
});
}
pos += 4;
let n = u32::from_le_bytes(data[pos..pos + 4].try_into().unwrap()) as usize;
let n_bytes = data.get(pos..pos + 4)
.ok_or(SKError::Truncated { context: "unitig index: n_unitigs" })?;
let n = u32::from_le_bytes(n_bytes.try_into().unwrap()) as usize;
pos += 4;
let seqls = data[pos..pos + n].to_vec();
let seqls = data.get(pos..pos + n)
.ok_or(SKError::Truncated { context: "unitig index: seqls" })?
.to_vec();
pos += n;
let mut packed_offsets = Vec::with_capacity(n + 1);
for _ in 0..=n {
packed_offsets.push(u32::from_le_bytes(data[pos..pos + 4].try_into().unwrap()));
let off_bytes = data.get(pos..pos + 4)
.ok_or(SKError::Truncated { context: "unitig index: packed_offsets" })?;
packed_offsets.push(u32::from_le_bytes(off_bytes.try_into().unwrap()));
pos += 4;
}