#[inline(always)]
pub(crate) fn read_u16_le(data: &[u8], offset: usize) -> Option<u16> {
let bytes: &[u8; 2] = data.get(offset..offset + 2)?.try_into().ok()?;
Some(u16::from_le_bytes(*bytes))
}
#[inline(always)]
pub(crate) fn read_u32_le(data: &[u8], offset: usize) -> Option<u32> {
let bytes: &[u8; 4] = data.get(offset..offset + 4)?.try_into().ok()?;
Some(u32::from_le_bytes(*bytes))
}
#[inline(always)]
pub(crate) fn read_i16_le(data: &[u8], offset: usize) -> Option<i16> {
let bytes: &[u8; 2] = data.get(offset..offset + 2)?.try_into().ok()?;
Some(i16::from_le_bytes(*bytes))
}
#[inline(always)]
pub(crate) fn read_i32_le(data: &[u8], offset: usize) -> Option<i32> {
let bytes: &[u8; 4] = data.get(offset..offset + 4)?.try_into().ok()?;
Some(i32::from_le_bytes(*bytes))
}
#[inline(always)]
pub(crate) fn read_u64_le(data: &[u8], offset: usize) -> Option<u64> {
let bytes: &[u8; 8] = data.get(offset..offset + 8)?.try_into().ok()?;
Some(u64::from_le_bytes(*bytes))
}
#[inline(always)]
pub(crate) fn read_i64_le(data: &[u8], offset: usize) -> Option<i64> {
let bytes: &[u8; 8] = data.get(offset..offset + 8)?.try_into().ok()?;
Some(i64::from_le_bytes(*bytes))
}
#[inline(always)]
pub(crate) fn read_f32_le(data: &[u8], offset: usize) -> Option<f32> {
let bytes: &[u8; 4] = data.get(offset..offset + 4)?.try_into().ok()?;
Some(f32::from_le_bytes(*bytes))
}
#[inline(always)]
pub(crate) fn read_f64_le(data: &[u8], offset: usize) -> Option<f64> {
let bytes: &[u8; 8] = data.get(offset..offset + 8)?.try_into().ok()?;
Some(f64::from_le_bytes(*bytes))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn u16_basic() {
assert_eq!(read_u16_le(&[0x34, 0x12], 0), Some(0x1234));
}
#[test]
fn u32_basic() {
assert_eq!(read_u32_le(&[0x78, 0x56, 0x34, 0x12], 0), Some(0x12345678));
}
#[test]
fn i16_negative() {
assert_eq!(read_i16_le(&[0x70, 0xFF], 0), Some(-144));
}
#[test]
fn i32_negative() {
assert_eq!(read_i32_le(&[0xFE, 0xFF, 0xFF, 0xFF], 0), Some(-2));
}
#[test]
fn u64_basic() {
assert_eq!(
read_u64_le(&[0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12], 0),
Some(0x1234567890ABCDEF)
);
}
#[test]
fn i64_negative() {
assert_eq!(
read_i64_le(&[0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], 0),
Some(-2)
);
}
#[test]
fn f32_basic() {
let val = read_f32_le(&1.5_f32.to_le_bytes(), 0);
assert_eq!(val, Some(1.5));
}
#[test]
fn f64_basic() {
let val = read_f64_le(&2.5_f64.to_le_bytes(), 0);
assert_eq!(val, Some(2.5));
}
#[test]
fn out_of_bounds_returns_none() {
assert_eq!(read_u16_le(&[0x01], 0), None);
assert_eq!(read_u32_le(&[0x01, 0x02, 0x03], 0), None);
assert_eq!(read_u16_le(&[0x01, 0x02], 1), None);
assert_eq!(read_u64_le(&[0x01, 0x02, 0x03, 0x04], 0), None);
}
}