use crate::err::DeserializationError;
pub(crate) fn read_array<const N: usize>(buf: &[u8], offset: usize) -> Option<[u8; N]> {
let end = offset.checked_add(N)?;
let bytes: [u8; N] = buf.get(offset..end)?.try_into().ok()?;
Some(bytes)
}
pub(crate) fn read_u8(buf: &[u8], offset: usize) -> Option<u8> {
buf.get(offset).copied()
}
#[cfg(feature = "wevt_templates")]
pub(crate) fn read_sig(buf: &[u8], offset: usize) -> Option<[u8; 4]> {
read_array::<4>(buf, offset)
}
pub(crate) fn read_u16_le(buf: &[u8], offset: usize) -> Option<u16> {
Some(u16::from_le_bytes(read_array::<2>(buf, offset)?))
}
pub(crate) fn read_u32_le(buf: &[u8], offset: usize) -> Option<u32> {
Some(u32::from_le_bytes(read_array::<4>(buf, offset)?))
}
pub(crate) fn read_u64_le(buf: &[u8], offset: usize) -> Option<u64> {
Some(u64::from_le_bytes(read_array::<8>(buf, offset)?))
}
#[inline]
fn truncated(what: &'static str, offset: usize, need: usize, len: usize) -> DeserializationError {
DeserializationError::Truncated {
what,
offset: offset as u64,
need,
have: len.saturating_sub(offset),
}
}
pub(crate) fn slice_r<'a>(
buf: &'a [u8],
offset: usize,
len: usize,
what: &'static str,
) -> Result<&'a [u8], DeserializationError> {
let end = offset
.checked_add(len)
.ok_or_else(|| truncated(what, offset, len, buf.len()))?;
buf.get(offset..end)
.ok_or_else(|| truncated(what, offset, len, buf.len()))
}
pub(crate) fn read_array_r<const N: usize>(
buf: &[u8],
offset: usize,
what: &'static str,
) -> Result<[u8; N], DeserializationError> {
read_array::<N>(buf, offset).ok_or_else(|| truncated(what, offset, N, buf.len()))
}
pub(crate) fn read_u16_le_r(
buf: &[u8],
offset: usize,
what: &'static str,
) -> Result<u16, DeserializationError> {
read_u16_le(buf, offset).ok_or_else(|| truncated(what, offset, 2, buf.len()))
}
pub(crate) fn read_u32_le_r(
buf: &[u8],
offset: usize,
what: &'static str,
) -> Result<u32, DeserializationError> {
read_u32_le(buf, offset).ok_or_else(|| truncated(what, offset, 4, buf.len()))
}
pub(crate) fn read_u64_le_r(
buf: &[u8],
offset: usize,
what: &'static str,
) -> Result<u64, DeserializationError> {
read_u64_le(buf, offset).ok_or_else(|| truncated(what, offset, 8, buf.len()))
}
pub(crate) fn read_u32_vec_le_r(
buf: &[u8],
offset: usize,
count: usize,
what: &'static str,
) -> Result<Vec<u32>, DeserializationError> {
let bytes = count
.checked_mul(4)
.ok_or_else(|| truncated(what, offset, usize::MAX, buf.len()))?;
let _ = slice_r(buf, offset, bytes, what)?;
let mut out = Vec::with_capacity(count);
for i in 0..count {
out.push(read_u32_le_r(buf, offset + i * 4, what)?);
}
Ok(out)
}