use crate::internal_prelude::v1::*;
use crate::{PackingResult, lib_get_slice, lib_get_mut_slice};
use super::types_bits::*;
#[derive(Default, Copy, Clone)]
pub struct Integer<T, B> {
num: T,
bits: PhantomData<B>
}
impl<T, B: NumberOfBits> Integer<T, B> {
fn sign_extend_bits() -> usize {
let native_bit_count = 8 * core::mem::size_of::<T>();
native_bit_count - B::number_of_bits()
}
}
impl<T, B> Debug for Integer<T, B> where T: Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.num)
}
}
impl<T, B> Display for Integer<T, B> where T: Display {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.num)
}
}
#[cfg(feature = "use_serde")]
mod serialize {
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer};
impl<T, B> Serialize for super::Integer<T, B> where T: Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
self.num.serialize(serializer)
}
}
impl<'de, T, B> Deserialize<'de> for super::Integer<T, B> where T: Deserialize<'de>, T: Into<super::Integer<T, B>> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
<T>::deserialize(deserializer).map(|n| n.into())
}
}
}
impl<T, B> PartialEq for Integer<T, B> where T: PartialEq {
fn eq(&self, other: &Self) -> bool {
self.num.eq(&other.num)
}
}
impl<T, B> Eq for Integer<T, B> where T: Eq {}
impl<T, B> Hash for Integer<T, B> where T: Hash {
fn hash<H: Hasher>(&self, state: &mut H) {
self.num.hash(state);
}
}
impl<T, B> Integer<T, B> where Self: Copy {
pub fn as_packed_msb(&self) -> MsbInteger<T, B, Self> {
MsbInteger(*self, Default::default(), Default::default())
}
pub fn as_packed_lsb(&self) -> LsbInteger<T, B, Self> {
LsbInteger(*self, Default::default(), Default::default())
}
}
pub trait SizedInteger<T, B: NumberOfBits> where Self: Sized {
fn value_bit_mask() -> T;
fn from_primitive(val: T) -> Self;
fn to_primitive(&self) -> T;
fn to_msb_bytes(&self) -> PackingResult<<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes>;
fn to_lsb_bytes(&self) -> PackingResult<<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes>;
fn from_msb_bytes(bytes: &<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes) -> PackingResult<Self>;
fn from_lsb_bytes(bytes: &<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes) -> PackingResult<Self>;
}
pub trait SizedIntegerSigned<T, B> : SizedInteger<T, B>
where B: NumberOfBits
{
fn from_unpacked_to_signed(val: T) -> T;
}
pub trait IntegerAsBytes where Self: Sized {
type AsBytes;
fn to_msb_bytes(&self) -> Self::AsBytes;
fn to_lsb_bytes(&self) -> Self::AsBytes;
fn from_msb_bytes(bytes: &Self::AsBytes) -> Self;
fn from_lsb_bytes(bytes: &Self::AsBytes) -> Self;
}
macro_rules! as_bytes {
(1, $v: expr) => {
[
(($v >> 0) as u8 & 0xFF)
]
};
(2, $v: expr) => {
[
(($v >> 8) as u8 & 0xFF),
(($v >> 0) as u8 & 0xFF),
]
};
(4, $v: expr) => {
[
(($v >> 24) as u8 & 0xFF),
(($v >> 16) as u8 & 0xFF),
(($v >> 8) as u8 & 0xFF),
(($v >> 0) as u8 & 0xFF)
]
};
(8, $v: expr) => {
[
(($v >> 56) as u8 & 0xFF),
(($v >> 48) as u8 & 0xFF),
(($v >> 40) as u8 & 0xFF),
(($v >> 32) as u8 & 0xFF),
(($v >> 24) as u8 & 0xFF),
(($v >> 16) as u8 & 0xFF),
(($v >> 8) as u8 & 0xFF),
(($v >> 0) as u8 & 0xFF)
]
}
}
macro_rules! from_bytes {
(1, $v: expr, $T: ident) => {
$v[0] as $T
};
(2, $v: expr, $T: ident) => {
(($v[0] as $T) << 8) |
(($v[1] as $T) << 0)
};
(4, $v: expr, $T: ident) => {
(($v[0] as $T) << 24) |
(($v[1] as $T) << 16) |
(($v[2] as $T) << 8) |
(($v[3] as $T) << 0)
};
(8, $v: expr, $T: ident) => {
(($v[0] as $T) << 56) |
(($v[1] as $T) << 48) |
(($v[2] as $T) << 40) |
(($v[3] as $T) << 32) |
(($v[4] as $T) << 24) |
(($v[5] as $T) << 16) |
(($v[6] as $T) << 8) |
(($v[7] as $T) << 0)
};
}
macro_rules! integer_as_bytes {
($T: ident, $N: tt) => {
impl IntegerAsBytes for $T {
type AsBytes = [u8; $N];
#[inline]
fn to_msb_bytes(&self) -> [u8; $N] {
as_bytes!($N, self)
}
#[inline]
fn to_lsb_bytes(&self) -> [u8; $N] {
let n = self.swap_bytes();
as_bytes!($N, n)
}
#[inline]
fn from_msb_bytes(bytes: &[u8; $N]) -> Self {
from_bytes!($N, bytes, $T)
}
#[inline]
fn from_lsb_bytes(bytes: &[u8; $N]) -> Self {
let n = from_bytes!($N, bytes, $T);
n.swap_bytes()
}
}
};
}
integer_as_bytes!(u8, 1);
integer_as_bytes!(i8, 1);
integer_as_bytes!(u16, 2);
integer_as_bytes!(i16, 2);
integer_as_bytes!(u32, 4);
integer_as_bytes!(i32, 4);
integer_as_bytes!(u64, 8);
integer_as_bytes!(i64, 8);
macro_rules! integer_bytes_impl {
($T: ident, $TB: ty; unsigned) => {
integer_bytes_impl!($T, $TB, unsigned);
};
($T: ident, $TB: ty; signed) => {
impl SizedIntegerSigned<$T, $TB> for Integer<$T, $TB> {
fn from_unpacked_to_signed(val: $T) -> $T {
let sign_extend_bits = Integer::<$T, $TB>::sign_extend_bits();
(val << sign_extend_bits) >> sign_extend_bits
}
}
integer_bytes_impl!($T, $TB, signed);
};
($VAL: ident; unsigned) => {
$VAL
};
($VAL: ident; signed) => {
Self::from_unpacked_to_signed($VAL)
};
($T: ident, $TB: ty, $SIGN: tt) => {
impl SizedInteger<$T, $TB> for Integer<$T, $TB> {
#[inline]
fn value_bit_mask() -> $T {
ones(<$TB>::number_of_bits() as u64) as $T
}
#[inline]
fn from_primitive(val: $T) -> Self {
let v = val & Self::value_bit_mask();
let v = integer_bytes_impl!(v; $SIGN);
Integer { num: v, bits: Default::default() }
}
#[inline]
fn to_primitive(&self) -> $T {
self.num
}
#[inline]
fn to_msb_bytes(&self) -> PackingResult<<<$TB as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes>
{
let mut ret: <<$TB as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes = Default::default();
let b = self.num.to_msb_bytes();
let skip = b.len() - ret.len();
let b = lib_get_slice(&b, skip..)?;
ret.copy_from_slice(b);
Ok(ret)
}
#[inline]
fn to_lsb_bytes(&self) -> PackingResult<<<$TB as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes>
{
let mut ret: <<$TB as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes = Default::default();
let b = self.num.to_lsb_bytes();
let take = ret.len();
let b = lib_get_slice(&b, 0..take)?;
ret.copy_from_slice(b);
Ok(ret)
}
#[inline]
fn from_msb_bytes(bytes: &<<$TB as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes) -> PackingResult<Self>
{
let mut native_bytes = Default::default();
{
<$T>::from_msb_bytes(&native_bytes);
}
let skip = native_bytes.len() - bytes.len();
{
let native_bytes = lib_get_mut_slice(&mut native_bytes, skip..)?;
native_bytes.copy_from_slice(&bytes[..]);
}
let v = <$T>::from_msb_bytes(&native_bytes);
Ok(Self::from_primitive(v))
}
#[inline]
fn from_lsb_bytes(bytes: &<<$TB as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes) -> PackingResult<Self>
{
let mut native_bytes = Default::default();
{
<$T>::from_lsb_bytes(&native_bytes);
}
{
let take = bytes.len();
let native_bytes = lib_get_mut_slice(&mut native_bytes, ..take)?;
native_bytes.copy_from_slice(&bytes[..]);
}
let v = <$T>::from_lsb_bytes(&native_bytes);
Ok(Self::from_primitive(v))
}
}
impl From<$T> for Integer<$T, $TB> {
fn from(v: $T) -> Self {
Self::from_primitive(v)
}
}
impl From<Integer<$T, $TB>> for $T {
fn from(v: Integer<$T, $TB>) -> Self {
v.to_primitive()
}
}
impl Deref for Integer<$T, $TB> {
type Target = $T;
fn deref(&self) -> &$T {
&self.num
}
}
};
}
macro_rules! bytes1_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<1>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<2>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<3>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<4>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<5>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<6>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<7>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<8>; $IS_SIGNED);
};
}
macro_rules! bytes2_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<9>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<10>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<11>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<12>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<13>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<14>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<15>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<16>; $IS_SIGNED);
};
}
macro_rules! bytes3_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<17>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<18>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<19>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<20>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<21>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<22>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<23>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<24>; $IS_SIGNED);
};
}
macro_rules! bytes4_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<25>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<26>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<27>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<28>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<29>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<30>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<31>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<32>; $IS_SIGNED);
};
}
macro_rules! bytes5_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<33>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<34>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<35>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<36>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<37>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<38>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<39>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<40>; $IS_SIGNED);
};
}
macro_rules! bytes6_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<41>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<42>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<43>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<44>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<45>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<46>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<47>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<48>; $IS_SIGNED);
};
}
macro_rules! bytes7_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<49>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<50>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<51>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<52>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<53>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<54>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<55>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<56>; $IS_SIGNED);
};
}
macro_rules! bytes8_impl {
($T: ident, $IS_SIGNED: tt) => {
integer_bytes_impl!($T, Bits::<57>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<58>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<59>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<60>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<61>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<62>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<63>; $IS_SIGNED);
integer_bytes_impl!($T, Bits::<64>; $IS_SIGNED);
};
}
bytes1_impl!(u8, unsigned);
bytes1_impl!(i8, signed);
bytes2_impl!(u16, unsigned);
bytes2_impl!(i16, signed);
bytes3_impl!(u32, unsigned);
bytes3_impl!(i32, signed);
bytes4_impl!(u32, unsigned);
bytes4_impl!(i32, signed);
bytes5_impl!(u64, unsigned);
bytes5_impl!(i64, signed);
bytes6_impl!(u64, unsigned);
bytes6_impl!(i64, signed);
bytes7_impl!(u64, unsigned);
bytes7_impl!(i64, signed);
bytes8_impl!(u64, unsigned);
bytes8_impl!(i64, signed);
const fn ones(n: u64) -> u64 {
if n == 0 { return 0; }
if n >= 64 { return !0; }
(1 << n) - 1
}
#[test]
fn test_u8() {
let byte: Integer<u8, Bits::<8>> = 0.into();
assert_eq!(0, *byte);
assert_eq!(0xFF, <Integer<u8, Bits::<8>>>::value_bit_mask());
}
#[test]
fn test_u16() {
let val = 0xABCD;
let num: Integer<u16, Bits::<16>> = val.into();
assert_eq!(val, *num);
assert_eq!([0xAB, 0xCD], num.to_msb_bytes().unwrap());
assert_eq!([0xCD, 0xAB], num.to_lsb_bytes().unwrap());
}
#[test]
fn test_u32() {
let val = 0x4589ABCD;
let num: Integer<u32, Bits::<32>> = val.into();
assert_eq!(val, *num);
assert_eq!([0x45, 0x89, 0xAB, 0xCD], num.to_msb_bytes().unwrap());
assert_eq!([0xCD, 0xAB, 0x89, 0x45], num.to_lsb_bytes().unwrap());
}
#[test]
fn test_u64() {
let val = 0x1122334455667788;
let num: Integer<u64, Bits::<64>> = val.into();
assert_eq!(val, *num);
assert_eq!([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], num.to_msb_bytes().unwrap());
assert_eq!([0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11], num.to_lsb_bytes().unwrap());
}
#[test]
fn test_roundtrip_u32() {
let val = 0x11223344;
let num: Integer<u32, Bits::<32>> = val.into();
let msb_bytes = num.to_msb_bytes().unwrap();
let from_msb = u32::from_msb_bytes(&msb_bytes);
assert_eq!(val, from_msb);
let lsb_bytes = num.to_lsb_bytes().unwrap();
let from_lsb = u32::from_lsb_bytes(&lsb_bytes);
assert_eq!(val, from_lsb);
}
#[test]
fn test_roundtrip_u24() {
let val = 0xCCBBAA;
let num: Integer<u32, Bits::<24>> = val.into();
let msb_bytes = num.to_msb_bytes().unwrap();
assert_eq!([0xCC, 0xBB, 0xAA], msb_bytes);
let from_msb = <Integer<u32, Bits::<24>>>::from_msb_bytes(&msb_bytes).unwrap();
assert_eq!(val, *from_msb);
let lsb_bytes = num.to_lsb_bytes().unwrap();
assert_eq!([0xAA, 0xBB, 0xCC], lsb_bytes);
let from_lsb = <Integer<u32, Bits::<24>>>::from_lsb_bytes(&lsb_bytes).unwrap();
assert_eq!(val, *from_lsb);
}
#[test]
fn test_roundtrip_u20() {
let val = 0xFBBAA;
let num: Integer<u32, Bits::<20>> = val.into();
let msb_bytes = num.to_msb_bytes().unwrap();
assert_eq!([0x0F, 0xBB, 0xAA], msb_bytes);
let from_msb = <Integer<u32, Bits::<20>>>::from_msb_bytes(&msb_bytes).unwrap();
assert_eq!(val, *from_msb);
}
use super::packing::{PackingError, PackedStruct, PackedStructInfo};
pub struct MsbInteger<T, B, I>(I, PhantomData<T>, PhantomData<B>);
impl<T, B, I> Deref for MsbInteger<T, B, I> {
type Target = I;
fn deref(&self) -> &I {
&self.0
}
}
impl<T, B, I> From<I> for MsbInteger<T, B, I> {
fn from(i: I) -> Self {
MsbInteger(i, Default::default(), Default::default())
}
}
impl<T, B, I> Debug for MsbInteger<T, B, I> where I: Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
impl<T, B, I> Display for MsbInteger<T, B, I> where I: Display {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<T, B, I> PackedStruct for MsbInteger<T, B, I>
where B: NumberOfBits, I: SizedInteger<T, B>
{
type ByteArray = <<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes;
fn pack(&self) -> PackingResult<<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes> {
self.0.to_msb_bytes()
}
#[inline]
fn unpack(src: &<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes) -> Result<Self, PackingError> {
let n = I::from_msb_bytes(src)?;
let n = MsbInteger(n, Default::default(), Default::default());
Ok(n)
}
}
impl<T, B, I> PackedStructInfo for MsbInteger<T, B, I> where B: NumberOfBits {
#[inline]
fn packed_bits() -> usize {
B::number_of_bits() as usize
}
}
pub struct LsbInteger<T, B, I>(I, PhantomData<T>, PhantomData<B>);
impl<T, B, I> Deref for LsbInteger<T, B, I> {
type Target = I;
fn deref(&self) -> &I {
&self.0
}
}
impl<T, B, I> From<I> for LsbInteger<T, B, I> {
fn from(i: I) -> Self {
LsbInteger(i, Default::default(), Default::default())
}
}
impl<T, B, I> Debug for LsbInteger<T, B, I> where I: Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
impl<T, B, I> Display for LsbInteger<T, B, I> where I: Display {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<T, B, I> PackedStruct for LsbInteger<T, B, I>
where B: NumberOfBits, I: SizedInteger<T, B>
{
type ByteArray = <<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes;
fn pack(&self) -> PackingResult<<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes> {
let mut bytes = self.0.to_lsb_bytes()?;
let l = B::byte_array_len() * 8;
let shift_by_bits = l - B::number_of_bits();
if shift_by_bits > 0 && (shift_by_bits % 8) != 0 {
use bitvec::prelude::*;
let leftover_bits = B::number_of_bits() % 8;
let bytes_slice = bytes.as_mut_bytes_slice();
let bits = BitSlice::<_, Msb0>::try_from_slice_mut(bytes_slice).map_err(|_| PackingError::BitsError)?;
let s = l - B::number_of_bits();
let (left, _) = bits.split_at_mut(l - leftover_bits);
left.shift_right(s);
}
Ok(bytes)
}
#[inline]
fn unpack(src: &<<B as NumberOfBits>::Bytes as NumberOfBytes>::AsBytes) -> PackingResult<Self> {
let l = B::byte_array_len() * 8;
let shift_by_bits = l - B::number_of_bits();
let n = if shift_by_bits > 0 && (shift_by_bits % 8) != 0 {
use bitvec::prelude::*;
let leftover_bits = B::number_of_bits() % 8;
let mut src_bytes = (*src).clone();
let bytes_slice = src_bytes.as_mut_bytes_slice();
let bits = BitSlice::<_, Msb0>::try_from_slice_mut(bytes_slice).map_err(|_| PackingError::BitsError)?;
let s = l - B::number_of_bits();
let (left, _) = bits.split_at_mut(l - leftover_bits);
left.shift_left(s);
I::from_lsb_bytes(&src_bytes)?
} else {
I::from_lsb_bytes(src)?
};
let n = LsbInteger(n, Default::default(), Default::default());
Ok(n)
}
}
impl<T, B, I> PackedStructInfo for LsbInteger<T, B, I> where B: NumberOfBits {
#[inline]
fn packed_bits() -> usize {
B::number_of_bits() as usize
}
}
#[test]
fn test_packed_int_msb() {
let val = 0xAABBCCDD;
let typed: Integer<u32, Bits::<32>> = val.into();
let endian = typed.as_packed_msb();
let packed = endian.pack().unwrap();
assert_eq!([0xAA, 0xBB, 0xCC, 0xDD], packed);
let unpacked: MsbInteger<_, _, Integer<u32, Bits::<32>>> = MsbInteger::unpack(&packed).unwrap();
assert_eq!(val, **unpacked);
}
#[test]
fn test_packed_int_partial() {
let val = 0b10_1010_1010;
let typed: Integer<u16, Bits::<10>> = val.into();
let endian = typed.as_packed_msb();
let packed = endian.pack().unwrap();
assert_eq!([0b00000010, 0b10101010], packed);
let unpacked: MsbInteger<_, _, Integer<u16, Bits::<10>>> = MsbInteger::unpack(&packed).unwrap();
assert_eq!(val, **unpacked);
}
#[test]
fn test_packed_int_lsb() {
let val = 0xAABBCCDD;
let typed: Integer<u32, Bits::<32>> = val.into();
let endian = typed.as_packed_lsb();
let packed = endian.pack().unwrap();
assert_eq!([0xDD, 0xCC, 0xBB, 0xAA], packed);
let unpacked: LsbInteger<_, _, Integer<u32, Bits::<32>>> = LsbInteger::unpack(&packed).unwrap();
assert_eq!(val, **unpacked);
}
#[test]
fn test_packed_int_lsb_partial_b10() {
let val = 0b10_1010_1011;
let typed: Integer<u16, Bits::<10>> = val.into();
let endian = typed.as_packed_lsb();
let packed = endian.pack().unwrap();
assert_eq!([0b00000010, 0b10101110], packed);
let unpacked: LsbInteger<_, _, Integer<u16, Bits::<10>>> = LsbInteger::unpack(&packed).unwrap();
assert_eq!(val, **unpacked);
}
#[test]
fn test_struct_info() {
fn get_bits<P: PackedStructInfo>(_s: &P) -> usize { P::packed_bits() }
let typed: Integer<u32, Bits::<30>> = 123.into();
let msb = typed.as_packed_msb();
assert_eq!(30, get_bits(&msb));
}
#[test]
fn test_slice_packing() {
use crate::packing::PackedStructSlice;
let mut data = vec![0xAA, 0xBB, 0xCC, 0xDD];
let unpacked = <MsbInteger<_, _, Integer<u32, Bits::<32>>>>::unpack_from_slice(&data).unwrap();
assert_eq!(0xAABBCCDD, **unpacked);
unpacked.pack_to_slice(&mut data).unwrap();
assert_eq!(&[0xAA, 0xBB, 0xCC, 0xDD], &data[..]);
}
#[test]
fn test_packed_int_lsb_sub() {
let val = 0xAABBCC;
let typed: Integer<u32, Bits::<24>> = val.into();
let endian = typed.as_packed_lsb();
let packed = endian.pack().unwrap();
assert_eq!([0xCC, 0xBB, 0xAA], packed);
}
#[test]
fn test_big_slice_unpacking() {
use crate::packing::PackedStructSlice;
let data = vec![0xAA, 0xBB, 0xCC, 0xDD];
let unpacked = <MsbInteger<_, _, Integer<u32, Bits::<32>>>>::unpack_from_slice(&data).unwrap();
assert_eq!(0xAABBCCDD, **unpacked);
}
#[test]
fn test_sign_extension() {
let val: Integer<i8, Bits::<4>> = 127_i8.into();
assert_eq!(*val, -1);
let val: Integer<i8, Bits::<4>> = 63_i8.into();
assert_eq!(*val, -1);
let val: Integer<i8, Bits::<4>> = 31_i8.into();
assert_eq!(*val, -1);
let val: Integer<i8, Bits::<4>> = 15_i8.into();
assert_eq!(*val, -1);
}
#[test]
fn test_sign_extension_limits() {
for i in -8..=7 {
let val: Integer<i8, Bits::<4>> = (i as i8).into();
assert_eq!(i, *val);
}
for i in -64..=63 {
let val: Integer<i8, Bits::<7>> = (i as i8).into();
assert_eq!(i, *val);
}
let val: Integer<i8, Bits::<8>> = (i8::MIN).into();
assert_eq!(*val, i8::MIN);
let val: Integer<i8, Bits::<8>> = (i8::MAX).into();
assert_eq!(*val, i8::MAX);
let val: Integer<i16, Bits::<16>> = (i16::MIN).into();
assert_eq!(*val, i16::MIN);
let val: Integer<i16, Bits::<16>> = (i16::MAX).into();
assert_eq!(*val, i16::MAX);
let val: Integer<i32, Bits::<32>> = (i32::MIN).into();
assert_eq!(*val, i32::MIN);
let val: Integer<i32, Bits::<32>> = (i32::MAX).into();
assert_eq!(*val, i32::MAX);
let val: Integer<i64, Bits::<64>> = (i64::MIN).into();
assert_eq!(*val, i64::MIN);
let val: Integer<i64, Bits::<64>> = (i64::MAX).into();
assert_eq!(*val, i64::MAX);
}