#[inline(always)]
pub fn read_u32_le(buf: &[u8], off: usize) -> u32 {
u32::from_le_bytes(buf[off..off + 4].try_into().unwrap())
}
#[inline(always)]
pub fn read_u64_le(buf: &[u8], off: usize) -> u64 {
u64::from_le_bytes(buf[off..off + 8].try_into().unwrap())
}
#[inline(always)]
pub fn read_i64_le(buf: &[u8], off: usize) -> i64 {
i64::from_le_bytes(buf[off..off + 8].try_into().unwrap())
}
mod sealed {
pub trait Sealed {}
}
pub trait LeScalar: Copy + sealed::Sealed {}
macro_rules! le_scalar {
($($t:ty),*) => { $(impl sealed::Sealed for $t {} impl LeScalar for $t {})* };
}
le_scalar!(u32, u64, i64);
#[inline(always)]
pub fn as_le_bytes<T: LeScalar>(v: &[T]) -> &[u8] {
unsafe { std::slice::from_raw_parts(v.as_ptr().cast::<u8>(), std::mem::size_of_val(v)) }
}
#[inline(always)]
pub fn as_le_bytes_mut<T: LeScalar>(v: &mut [T]) -> &mut [u8] {
unsafe { std::slice::from_raw_parts_mut(v.as_mut_ptr().cast::<u8>(), std::mem::size_of_val(v)) }
}
pub fn extend_from_le_bytes<T: LeScalar>(dst: &mut Vec<T>, src: &[u8]) {
let size = std::mem::size_of::<T>();
assert!(
src.len().is_multiple_of(size),
"extend_from_le_bytes: {} bytes is not a whole number of {size}-byte scalars",
src.len()
);
let (base, n) = (dst.len(), src.len() / size);
dst.reserve(n);
unsafe {
std::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().add(base).cast::<u8>(), src.len());
dst.set_len(base + n);
}
}
#[inline(always)]
pub fn read_signed_exact(bytes: &[u8]) -> i64 {
match bytes.len() {
1 => bytes[0] as i8 as i64,
2 => i16::from_le_bytes(bytes.try_into().unwrap()) as i64,
4 => i32::from_le_bytes(bytes.try_into().unwrap()) as i64,
8 => i64::from_le_bytes(bytes.try_into().unwrap()),
_ => unreachable!("read_signed_exact: unexpected column width"),
}
}
#[inline(always)]
pub fn read_unsigned_exact(bytes: &[u8]) -> u64 {
match bytes.len() {
1 => bytes[0] as u64,
2 => u16::from_le_bytes(bytes.try_into().unwrap()) as u64,
4 => u32::from_le_bytes(bytes.try_into().unwrap()) as u64,
8 => u64::from_le_bytes(bytes.try_into().unwrap()),
_ => unreachable!("read_unsigned_exact: unexpected column width"),
}
}
#[inline(always)]
pub const fn low_bits_mask(n: usize) -> u64 {
if n < 64 {
(1u64 << n) - 1
} else {
u64::MAX
}
}
pub struct BitIter(pub u64);
impl Iterator for BitIter {
type Item = usize;
#[inline(always)]
fn next(&mut self) -> Option<usize> {
if self.0 == 0 {
return None;
}
let i = self.0.trailing_zeros() as usize;
self.0 &= self.0 - 1;
Some(i)
}
}
#[inline(always)]
pub fn write_u32_le(buf: &mut [u8], off: usize, val: u32) {
buf[off..off + 4].copy_from_slice(&val.to_le_bytes());
}
#[inline(always)]
pub fn write_u64_le(buf: &mut [u8], off: usize, val: u64) {
buf[off..off + 8].copy_from_slice(&val.to_le_bytes());
}
#[cfg(test)]
#[path = "tests/bytes.rs"]
mod tests;