#![cfg(test)]
use core::cmp;
use crate::{
index::BitIdx,
prelude::*,
ptr::{
self as bv_ptr,
AddressExt,
BitSpan,
BitSpanError,
Mut,
},
};
#[test]
fn free_functions() {
let mut a = [0u8, !0];
let mut b = 255u16;
let one = BitPtr::<Mut, u8, Lsb0>::from_slice_mut(&mut a[..]);
let two = one.wrapping_add(8);
let three = BitPtr::<Mut, u16, Msb0>::from_mut(&mut b);
let four = three.wrapping_add(8);
unsafe {
bv_ptr::copy(two.to_const(), one, 8);
}
assert_eq!(a[0], !0);
unsafe {
bv_ptr::copy(three.to_const(), one, 8);
}
assert_eq!(a[0], 0);
assert!(!bv_ptr::eq(two.to_const(), one.to_const()));
unsafe {
bv_ptr::swap_nonoverlapping(two, three, 8);
}
assert_eq!(a[1], 0);
assert_eq!(b, !0);
unsafe {
bv_ptr::write_bits(four, false, 8);
}
assert_eq!(b, 0xFF00);
}
#[test]
fn alignment() {
let data = 0u16;
let a = unsafe { (&data).into_address() };
let b = a.cast::<u8>().wrapping_add(1).cast::<u16>();
assert!(bv_ptr::check_alignment(a).is_ok());
assert!(bv_ptr::check_alignment(b).is_err());
}
#[test]
fn proxy() {
let mut data = 0u8;
{
let bits = data.view_bits_mut::<Lsb0>();
let (mut a, rest) = bits.split_first_mut().unwrap();
let (mut b, _) = rest.split_first_mut().unwrap();
assert!(!a.replace(true));
a.swap(&mut b);
assert!(*b);
a.set(true);
}
assert_eq!(data, 3);
}
#[test]
fn range() {
let data = 0u8;
let mut bpr = data.view_bits::<Lsb0>().as_bitptr_range();
let range = bpr.clone().into_range();
let bpr2 = range.into();
assert_eq!(bpr, bpr2);
assert!(bpr.nth_back(9).is_none());
}
#[test]
#[allow(deprecated)]
fn single() {
let mut data = 1u16;
let bp = data.view_bits_mut::<Lsb0>().as_mut_bitptr();
assert!(!bp.is_null());
let bp2 = bp.wrapping_add(9);
assert_ne!(bp2.pointer().cast::<u8>(), bp2.cast::<u8>().pointer());
assert!(unsafe { bp.read_volatile() });
assert!(unsafe { bp.read_unaligned() });
assert_eq!(bp.align_offset(2), 0);
assert_eq!(bp2.align_offset(2), 7);
unsafe {
bp.write_volatile(false);
bp.swap(bp2);
bp2.write_unaligned(true);
}
assert_eq!(bp.cmp(&bp2), cmp::Ordering::Less);
assert_ne!(bp, bp.cast::<u8>());
assert!(bp.partial_cmp(&bp.cast::<u8>()).is_none());
}
#[test]
fn span() {
let mut data = [0u32; 2];
let addr = unsafe { data.as_mut_ptr().into_address() };
let too_long = BitSpan::<Mut, u32, Lsb0>::REGION_MAX_BITS + 1;
assert!(matches!(
BitSpan::<_, _, Lsb0>::new(addr, BitIdx::MIN, too_long),
Err(BitSpanError::TooLong(ct)) if ct == too_long));
let bp = data.view_bits_mut::<Lsb0>().as_mut_bitptr();
let bs = bp.cast::<u8>().wrapping_add(8).span(32).unwrap();
let (l, c, r) = unsafe { bs.align_to::<u16>() };
assert_eq!(l.len(), 8);
assert_eq!(c.len(), 16);
assert_eq!(r.len(), 8);
let bs2 = bp.cast::<u8>().wrapping_add(3).span(3).unwrap();
assert_eq!(
unsafe { bs2.align_to::<u16>() },
(bs2, BitSpan::EMPTY, BitSpan::EMPTY)
);
}
#[test]
#[cfg(feature = "alloc")]
fn format() {
#[cfg(not(feature = "std"))]
use alloc::format;
use core::any;
let data = 1u8;
let bits = data.view_bits::<Lsb0>();
let bit = bits.first().unwrap();
let render = format!("{:?}", bit);
assert!(render.starts_with("BitRef<u8,"));
assert!(render.ends_with("bits: 1, bit: true }"));
let bitptr = bits.as_bitptr();
let render = format!("{:?}", bitptr);
assert!(render.starts_with("*const Bit<u8,"));
assert!(render.ends_with(", 000)"), "{}", render);
let bitspan = bitptr.wrapping_add(2).span(3).unwrap();
let render = format!("{:?}", bitspan);
let expected = format!(
"BitSpan<u8, {}> {{ addr: {:p}, head: 010, bits: 3 }}",
any::type_name::<Lsb0>(),
bitspan.address(),
);
assert_eq!(render, expected);
let render = format!("{:p}", bitspan);
let expected = format!("{:p}(010)[3]", bitspan.address());
assert_eq!(render, expected);
}