Documentation
use crate::error::{EmapiError, Result};

pub fn read_uint16(data: &[u8], offset: usize) -> Result<u16> {
  check_range(data, offset, 2)?;
  Ok(u16::from_le_bytes([data[offset], data[offset + 1]]))
}

pub fn read_int16(data: &[u8], offset: usize) -> Result<i16> {
  Ok(read_uint16(data, offset)? as i16)
}

pub fn read_uint32(data: &[u8], offset: usize) -> Result<u32> {
  check_range(data, offset, 4)?;
  Ok(u32::from_le_bytes([
    data[offset],
    data[offset + 1],
    data[offset + 2],
    data[offset + 3],
  ]))
}

pub fn uint16(value: u16) -> [u8; 2] {
  value.to_le_bytes()
}

pub fn uint32(value: u32) -> [u8; 4] {
  value.to_le_bytes()
}

pub fn write_uint16(data: &mut [u8], offset: usize, value: u16) -> Result<()> {
  check_range(data, offset, 2)?;
  data[offset..offset + 2].copy_from_slice(&uint16(value));
  Ok(())
}

pub fn write_uint32(data: &mut [u8], offset: usize, value: u32) -> Result<()> {
  check_range(data, offset, 4)?;
  data[offset..offset + 4].copy_from_slice(&uint32(value));
  Ok(())
}

fn check_range(data: &[u8], offset: usize, length: usize) -> Result<()> {
  if offset
    .checked_add(length)
    .is_none_or(|end| end > data.len())
  {
    return Err(EmapiError::NotEnoughData {
      offset,
      length,
      data_len: data.len(),
    });
  }
  Ok(())
}