use super::rational::{IRational, URational};
use std::convert::TryInto;
#[inline(always)]
pub(crate) fn read_u16(le: bool, raw: &[u8]) -> Option<u16> {
let bytes = raw.get(..2)?.try_into().ok()?;
Some(if le {
u16::from_le_bytes(bytes)
} else {
u16::from_be_bytes(bytes)
})
}
#[inline(always)]
pub(crate) fn read_i16(le: bool, raw: &[u8]) -> Option<i16> {
let bytes = raw.get(..2)?.try_into().ok()?;
Some(if le {
i16::from_le_bytes(bytes)
} else {
i16::from_be_bytes(bytes)
})
}
#[inline(always)]
pub(crate) fn read_u32(le: bool, raw: &[u8]) -> Option<u32> {
let bytes = raw.get(..4)?.try_into().ok()?;
Some(if le {
u32::from_le_bytes(bytes)
} else {
u32::from_be_bytes(bytes)
})
}
#[inline(always)]
pub(crate) fn read_i32(le: bool, raw: &[u8]) -> Option<i32> {
let bytes = raw.get(..4)?.try_into().ok()?;
Some(if le {
i32::from_le_bytes(bytes)
} else {
i32::from_be_bytes(bytes)
})
}
#[inline(always)]
pub(crate) fn read_f32(raw: &[u8]) -> Option<f32> {
raw.get(..4)?.try_into().ok().map(f32::from_le_bytes)
}
#[inline(always)]
pub(crate) fn read_f64(raw: &[u8]) -> Option<f64> {
raw.get(..8)?.try_into().ok().map(f64::from_le_bytes)
}
#[inline(always)]
pub(crate) fn read_urational(le: bool, raw: &[u8]) -> Option<URational> {
let n = read_u32(le, &raw[0..4])?;
let d = read_u32(le, &raw[4..8])?;
Some(URational { numerator: n, denominator: d })
}
#[inline(always)]
pub(crate) fn read_irational(le: bool, raw: &[u8]) -> Option<IRational> {
let n = read_i32(le, &raw[0..4])?;
let d = read_i32(le, &raw[4..8])?;
Some(IRational { numerator: n, denominator: d })
}
#[inline(always)]
fn read_elements<T>(size: u8, count: u32, raw: &[u8], convert: impl Fn(&[u8]) -> T) -> Option<Vec<T>> {
let count = count as usize;
let size = size as usize;
let byte_size = size.checked_mul(count)?;
let bytes = raw.get(..byte_size)?;
let mut out = Vec::new();
out.try_reserve_exact(count).ok()?;
out.extend(bytes.chunks_exact(size).map(convert).take(count));
Some(out)
}
pub(crate) fn read_i8_array(count: u32, raw: &[u8]) -> Option<Vec<i8>> {
Some(raw.get(..count as usize)?.iter().map(|&i| i as i8).collect())
}
#[inline(never)]
pub(crate) fn read_u16_array(le: bool, count: u32, raw: &[u8]) -> Option<Vec<u16>> {
read_elements(2, count, raw, move |ch| read_u16(le, ch).unwrap())
}
pub(crate) fn read_i16_array(le: bool, count: u32, raw: &[u8]) -> Option<Vec<i16>> {
read_elements(2, count, raw, move |ch| read_i16(le, ch).unwrap())
}
pub(crate) fn read_u32_array(le: bool, count: u32, raw: &[u8]) -> Option<Vec<u32>> {
read_elements(4, count, raw, move |ch| read_u32(le, ch).unwrap())
}
pub(crate) fn read_i32_array(le: bool, count: u32, raw: &[u8]) -> Option<Vec<i32>> {
read_elements(4, count, raw, move |ch| read_i32(le, ch).unwrap())
}
pub(crate) fn read_f32_array(count: u32, raw: &[u8]) -> Option<Vec<f32>> {
read_elements(4, count, raw, move |ch| read_f32(ch).unwrap())
}
pub(crate) fn read_f64_array(count: u32, raw: &[u8]) -> Option<Vec<f64>> {
read_elements(8, count, raw, move |ch| read_f64(ch).unwrap())
}
pub(crate) fn read_urational_array(le: bool, count: u32, raw: &[u8]) -> Option<Vec<URational>> {
read_elements(8, count, raw, move |ch| read_urational(le, ch).unwrap())
}
pub(crate) fn read_irational_array(le: bool, count: u32, raw: &[u8]) -> Option<Vec<IRational>> {
read_elements(8, count, raw, move |ch| read_irational(le, ch).unwrap())
}