use crate::ops::Len;
use crate::types::Idx;
use std::mem;
pub trait BitSrc: Len {
unsafe fn read_bytes(&self, idx: Idx) -> usize;
fn base(&self) -> Idx;
}
impl<'a> BitSrc for &'a [u8] {
#[inline(always)]
unsafe fn read_bytes(&self, idx: Idx) -> usize {
let index = isize::from(idx);
if index >= 0 {
debug_assert!(index as usize + mem::size_of::<usize>() <= self.len());
self.as_ptr().add(index as usize).cast::<usize>().read_unaligned().to_le()
} else {
0
}
}
#[inline(always)]
fn base(&self) -> Idx {
assert!(8 <= self.len());
assert!(self.len() <= u32::MAX as usize);
Idx::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(target_pointer_width = "64")]
#[test]
fn read_bytes_9() {
let src = b"********123456789".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::new(9)) }, 0x3938_3736_3534_3332);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn read_bytes_8() {
let src = b"********123456789".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::new(8)) }, 0x3837_3635_3433_3231);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn read_bytes_0() {
let src = b"********123456789".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::new(0)) }, 0x2A2A_2A2A_2A2A_2A2A);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn read_bytes_neg() {
let src = b"********123456789".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::default() - 1) }, 0x0000_0000_0000_0000);
}
#[cfg(target_pointer_width = "32")]
#[test]
fn read_bytes_9() {
let src = b"********12345".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::new(9)) }, 0x3534_3332);
}
#[cfg(target_pointer_width = "32")]
#[test]
fn read_bytes_8() {
let src = b"********123456789".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::new(8)) }, 0x3433_3231);
}
#[cfg(target_pointer_width = "32")]
#[test]
fn read_bytes_0() {
let src = b"********123456789".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::new(0)) }, 0x2A2A_2A2A);
}
#[cfg(target_pointer_width = "32")]
#[test]
fn read_bytes_neg() {
let src = b"********123456789".as_ref();
assert_eq!(unsafe { src.read_bytes(Idx::default() - 1) }, 0x0000_0000);
}
}