#![no_std]
pub use bitregions_impl::bitregions;
#[cfg(test)]
mod test {
use super::*;
bitregions! {
pub Test u16 {
LOW_REGION: 0b00000111 | 0..=5,
HIGH_REGION: 0b00011000,
HIGH_TOGGLE: 0b01000000,
}
pub fn with_regions(high: u8, low: u8) -> Test {
let mut r = Test::new(0u16);
r.set_high_region(high);
r.set_low_region(low);
r
}
}
bitregions! {
pub DefaultLitAddrTest u16 @ 0xC0FFEE {
HIGH_TOGGLE: 0b01000000,
}
}
const DEFAULT_ADDR_CONST: usize = 0xDEADBEEF;
bitregions! {
pub DefaultConstAddrTest u16 @ DEFAULT_ADDR_CONST {
HIGH_TOGGLE: 0b01000000,
}
}
bitregions! {
pub DefaultExprAddrTest u16 @ DEFAULT_ADDR_CONST + 0x80 {
HIGH_TOGGLE: 0b01000000,
}
}
bitregions! {
pub WideRegionTest u32 @ DEFAULT_ADDR_CONST + 0x80 {
BITS6: 0b00000000000000000000000000111111,
BITS10: 0b00000000000000011111111110000000,
BITS15: 0b11111111111111100000000000000000,
}
}
#[test]
fn default_impl() {
assert_eq!(Test::default().raw(), 0);
assert_eq!(DefaultLitAddrTest::default().raw(), 0);
assert_eq!(DefaultConstAddrTest::default().raw(), 0);
assert_eq!(DefaultExprAddrTest::default().raw(), 0);
assert_eq!(WideRegionTest::default().raw(), 0);
}
#[test]
fn with_ctors() {
assert_eq!(Test::with_high_toggle(), Test::HIGH_TOGGLE.into());
assert_eq!(Test::with_low_region(4u8), Test::new(4u16));
assert_eq!(Test::with_high_region(3u8), Test::new(3u16 << 3));
}
#[test]
fn user_fns() {
let mut expect = Test::new(0u16);
expect.set_low_region(4u8);
expect.set_high_region(3u8);
assert_eq!(expect, Test::with_regions(3, 4));
}
#[test]
fn get_set_low_region() {
let mut test = Test::from(0);
assert!(0 == test.low_region());
test.set_low_region(5u8);
assert!(5 == test.low_region());
test.set_low_region(2u8);
assert!(2 == test.low_region());
test.set_low_region(4u8);
assert!(4 == test.low_region());
test.set_low_region(0u8);
assert!(0 == test.low_region());
}
#[test]
fn get_low_region_tuple() {
let mut test = Test::with_low_region(5u8);
let mut tup = test.low_region_tuple();
assert_eq!(tup, (1,0,1));
test.set_low_region(1u8);
tup = test.low_region_tuple();
assert_eq!(tup, (0,0,1));
test.set_low_region(4u8);
tup = test.low_region_tuple();
assert_eq!(tup, (1,0,0));
}
#[test]
fn get_low_region_bools() {
let mut test = Test::with_low_region(5u8);
let mut bools = test.low_region_bools();
assert_eq!(bools, (true,false,true));
test.set_low_region(1u8);
bools = test.low_region_bools();
assert_eq!(bools, (false,false,true));
test.set_low_region(4u8);
bools = test.low_region_bools();
assert_eq!(bools, (true,false,false));
}
#[test]
#[should_panic]
fn set_beyond_low_region() {
let mut test = Test::from(0);
test.set_low_region(8u8);
}
#[test]
#[should_panic]
fn set_low_region_outside_range() {
let mut test = Test::from(0);
test.set_low_region(6u8);
}
#[test]
fn get_set_high_region() {
let mut test = Test::from(0);
assert!(0 == test.high_region());
test.set_high_region(2u8);
assert!(2 == test.high_region());
test.set_low_region(3u8);
assert!(3 == test.low_region());
test.set_high_region(0u8);
assert!(0 == test.high_region());
}
#[test]
fn get_high_region_tuple() {
let mut test = Test::with_high_region(1u8);
let mut tup = test.high_region_tuple();
assert_eq!(tup, (0,1));
test.set_high_region(3u8);
tup = test.high_region_tuple();
assert_eq!(tup, (1,1));
test.set_high_region(0u8);
tup = test.high_region_tuple();
assert_eq!(tup, (0,0));
}
#[test]
fn get_high_region_bools() {
let mut test = Test::with_high_region(1u8);
let mut bools = test.high_region_bools();
assert_eq!(bools, (false,true));
test.set_high_region(3u8);
bools = test.high_region_bools();
assert_eq!(bools, (true,true));
test.set_high_region(0u8);
bools = test.high_region_bools();
assert_eq!(bools, (false,false));
}
#[test]
#[should_panic]
fn set_beyond_high_region() {
let mut test = Test::from(0);
test.set_high_region(4u8);
}
#[test]
fn toggle() {
let mut test = Test::from(0);
assert!(!test.high_toggle());
test.toggle_high_toggle();
assert!(test.high_toggle());
test.toggle_high_toggle();
assert!(!test.high_toggle());
}
#[test]
fn set_single_bit() {
let mut test = Test::from(0);
assert!(!test.high_toggle());
test.set_high_toggle();
assert!(test.high_toggle());
test.set_high_toggle();
assert!(test.high_toggle());
}
#[test]
fn unset_single_bit() {
let mut test = Test::from(0);
assert!(!test.high_toggle());
test.set_high_toggle();
assert!(test.high_toggle());
test.unset_high_toggle();
assert!(!test.high_toggle());
test.unset_high_toggle();
assert!(!test.high_toggle());
}
#[test]
fn at_addr() {
let mut mem: [u8; 4096] = [0u8; 4096];
let u16_ptr = &mut mem[8] as *mut _ as *mut u16;
let test = unsafe {
Test::at_addr_mut(&mut mem[8] as *mut _ as usize)
};
assert_eq!(unsafe{*u16_ptr}, 0);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.set_high_region(3u8);
assert_eq!(unsafe{*u16_ptr}, 0b11000);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.set_low_region(5u8);
assert_eq!(unsafe{*u16_ptr}, 0b11101);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.toggle_high_toggle();
assert_eq!(unsafe{*u16_ptr}, 0b1011101);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.toggle_high_toggle();
assert_eq!(unsafe{*u16_ptr}, 0b0011101);
assert_eq!(unsafe{*u16_ptr}, test.raw());
}
#[test]
fn at_ref() {
let mut mem: [u8; 4096] = [0u8; 4096];
let u16_ptr = &mut mem[16] as *mut _ as *mut u16;
let test = unsafe { Test::at_ref_mut(&mut mem[16]) };
assert_eq!(unsafe{*u16_ptr}, 0);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.set_high_region(3u8);
assert_eq!(unsafe{*u16_ptr}, 0b11000);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.set_low_region(5u8);
assert_eq!(unsafe{*u16_ptr}, 0b11101);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.toggle_high_toggle();
assert_eq!(unsafe{*u16_ptr}, 0b1011101);
assert_eq!(unsafe{*u16_ptr}, test.raw());
test.toggle_high_toggle();
assert_eq!(unsafe{*u16_ptr}, 0b0011101);
assert_eq!(unsafe{*u16_ptr}, test.raw());
}
#[test]
fn math_ops() {
assert_eq!(Test::new(18u16), Test::new(3u16) + Test::new(15u16));
assert_eq!(Test::new(7u16), Test::new(20u16) - Test::new(13u16));
assert_eq!(Test::new(18u16), Test::new(6u16) * Test::new(3u16));
assert_eq!(Test::new(3u16), Test::new(24u16) / Test::new(8u16));
}
#[test]
fn math_assign_ops() {
let mut add_test = Test::new(3u16);
add_test += Test::new(15u16);
assert_eq!(Test::new(18u16), add_test);
let mut sub_test = Test::new(20u16);
sub_test -= Test::new(13u16);
assert_eq!(Test::new(7u16), sub_test);
let mut mul_test = Test::new(6u16);
mul_test *= Test::new(3u16);
assert_eq!(Test::new(18u16), mul_test);
let mut div_test = Test::new(24u16);
div_test /= Test::new(8u16);
assert_eq!(Test::new(3u16), div_test);
}
#[test]
fn bit_ops() {
assert_eq!(Test::new(0xB4u16), Test::new(0xB0u16) | Test::new(0x04u16));
assert_eq!(Test::new(0x04u16), Test::new(0xD7u16) & Test::new(0x04u16));
assert_eq!(Test::new(0b001100u16), Test::new(0b110011u16) ^ Test::new(0b111111u16));
assert_eq!(Test::new(8u16), Test::new(2u16) << Test::new(2u16));
assert_eq!(Test::new(1u16), Test::new(8u16) >> Test::new(3u16));
}
#[test]
fn bit_assign_ops() {
let mut or_test = Test::new(0xB0u16);
or_test |= Test::new(0x04u16);
assert_eq!(Test::new(0xB4u16), or_test);
let mut and_test = Test::new(0xD7u16);
and_test &= Test::new(0x04u16);
assert_eq!(Test::new(4u16), and_test);
let mut xor_test = Test::new(0b110011u16);
xor_test ^= Test::new(0b111111u16);
assert_eq!(Test::new(0b001100u16), xor_test);
let mut shl_test = Test::new(1u16);
shl_test <<= Test::new(3u16);
assert_eq!(Test::new(8u16), shl_test);
let mut shr_test = Test::new(8u16);
shr_test >>= Test::new(3u16);
assert_eq!(Test::new(1u16), shr_test);
}
#[test]
fn default_ptr_lit() {
let ptr = unsafe { DefaultLitAddrTest::default_ptr() };
assert_eq!(ptr as *mut _ as usize, 0xC0FFEE);
}
#[test]
fn default_ptr_ident() {
let ptr = unsafe { DefaultConstAddrTest::default_ptr() };
assert_eq!(ptr as *mut _ as usize, DEFAULT_ADDR_CONST);
}
#[test]
fn default_ptr_expr() {
let ptr = unsafe { DefaultExprAddrTest::default_ptr() };
assert_eq!(ptr as *mut _ as usize, DEFAULT_ADDR_CONST + 0x80);
}
#[test]
fn wide_region_getters() {
let mut test = WideRegionTest::new(0u32);
test.set_bits6(10u8);
test.set_bits10(1023u16);
test.set_bits15(1234u16);
let bits6: u8 = test.bits6();
assert_eq!(bits6, 10u8);
let bits10: u16 = test.bits10();
assert_eq!(bits10, 1023u16);
let bits15: u16 = test.bits15();
assert_eq!(bits15, 1234u16);
}
#[test]
fn wide_region_tuples() {
let mut test = WideRegionTest::new(0u32);
test.set_bits6(10u8);
test.set_bits10(1023u16);
test.set_bits15(1234u16);
assert_eq!(test.bits6_tuple(), (0,0,1,0,1,0));
assert_eq!(test.bits6_bools(), (false,false,true,false,true,false));
}
}