pub trait BlockRead {
type Error: core::fmt::Debug;
fn read_at(&mut self, offset_bytes: u64, buf: &mut [u8]) -> Result<(), Self::Error>;
}
pub(crate) fn read_exact<R: BlockRead>(
reader: &mut R,
off: u64,
buf: &mut [u8],
token: &'static str,
) -> crate::error::Result<()> {
reader
.read_at(off, buf)
.map_err(|_| crate::error::Error::Io { token, offset: off })
}
#[inline]
pub(crate) fn u16_at(b: &[u8], o: usize) -> Option<u16> {
b.get(o..o + 2)?.try_into().ok().map(u16::from_le_bytes)
}
#[inline]
pub(crate) fn u32_at(b: &[u8], o: usize) -> Option<u32> {
b.get(o..o + 4)?.try_into().ok().map(u32::from_le_bytes)
}
#[inline]
pub(crate) fn u64_at(b: &[u8], o: usize) -> Option<u64> {
b.get(o..o + 8)?.try_into().ok().map(u64::from_le_bytes)
}