mod common;
use bitpiece::*;
use common::expect_panic;
#[bitpiece(8, all)]
#[derive(Debug, PartialEq, Eq)]
struct BasicStruct {
a: B3,
b: B5,
}
bitpiece_check_full_impl! {BasicStruct, true}
#[test]
fn basic_struct_bit_len() {
assert_eq!(BASIC_STRUCT_BIT_LEN, 8);
assert_eq!(BasicStruct::BITS, 8);
}
#[test]
fn basic_struct_storage_type() {
let _: BasicStructStorageTy = 0u8;
}
#[test]
fn basic_struct_field_constants() {
assert_eq!(BasicStruct::A_OFFSET, 0);
assert_eq!(BasicStruct::A_LEN, 3);
assert_eq!(BasicStruct::B_OFFSET, 3);
assert_eq!(BasicStruct::B_LEN, 5);
}
#[test]
fn basic_struct_from_bits() {
let val = BasicStruct::from_bits(0b11111_010);
assert_eq!(val.a(), B3::new(0b010));
assert_eq!(val.b(), B5::new(0b11111));
}
#[test]
fn basic_struct_to_bits() {
let val = BasicStruct::from_bits(0b11111_010);
assert_eq!(val.to_bits(), 0b11111_010);
}
#[test]
fn basic_struct_try_from_bits() {
let val = BasicStruct::try_from_bits(0b11111_010);
assert!(val.is_some());
assert_eq!(val.unwrap().a(), B3::new(0b010));
}
#[test]
fn struct_field_getters() {
let val = BasicStruct::from_bits(0b10101_011);
assert_eq!(val.a(), B3::new(0b011));
assert_eq!(val.b(), B5::new(0b10101));
}
#[test]
fn struct_field_getters_boundary_values() {
let val = BasicStruct::from_bits(0b00000_000);
assert_eq!(val.a(), B3::new(0));
assert_eq!(val.b(), B5::new(0));
let val = BasicStruct::from_bits(0b11111_111);
assert_eq!(val.a(), B3::new(7));
assert_eq!(val.b(), B5::new(31));
}
#[test]
fn struct_field_setters() {
let mut val = BasicStruct::ZEROES;
assert_eq!(val.a(), B3::new(0));
assert_eq!(val.b(), B5::new(0));
val.set_a(B3::new(5));
assert_eq!(val.a(), B3::new(5));
assert_eq!(val.b(), B5::new(0));
val.set_b(B5::new(20));
assert_eq!(val.a(), B3::new(5));
assert_eq!(val.b(), B5::new(20));
}
#[test]
fn struct_field_setters_overwrite() {
let mut val = BasicStruct::from_bits(0xFF);
assert_eq!(val.a(), B3::new(7));
assert_eq!(val.b(), B5::new(31));
val.set_a(B3::new(0));
assert_eq!(val.a(), B3::new(0));
assert_eq!(val.b(), B5::new(31)); }
#[test]
fn struct_with_methods() {
let val = BasicStruct::ZEROES.with_a(B3::new(5)).with_b(B5::new(20));
assert_eq!(val.a(), B3::new(5));
assert_eq!(val.b(), B5::new(20));
}
#[test]
fn struct_with_methods_chaining() {
let val = BasicStruct::ZEROES
.with_a(B3::new(1))
.with_b(B5::new(2))
.with_a(B3::new(3)) .with_b(B5::new(4)); assert_eq!(val.a(), B3::new(3));
assert_eq!(val.b(), B5::new(4));
}
#[test]
fn struct_with_methods_immutable() {
let original = BasicStruct::ZEROES;
let modified = original.with_a(B3::new(5));
assert_eq!(original.a(), B3::new(0));
assert_eq!(modified.a(), B3::new(5));
}
#[test]
fn struct_noshift_getters() {
let val = BasicStruct::from_bits(0b10101_011);
assert_eq!(val.a_noshift(), 0b011);
assert_eq!(val.b_noshift(), 0b10101_000);
}
#[test]
fn struct_zeroes_constant() {
let val = BasicStruct::ZEROES;
assert_eq!(val.storage, 0);
assert_eq!(val.a(), B3::new(0));
assert_eq!(val.b(), B5::new(0));
}
#[test]
fn struct_ones_constant() {
let val = BasicStruct::ONES;
assert_eq!(val.storage, 0xFF);
assert_eq!(val.a(), B3::new(7));
assert_eq!(val.b(), B5::new(31));
}
#[test]
fn struct_min_max_constants() {
assert_eq!(BasicStruct::MIN.storage, BasicStruct::ZEROES.storage);
assert_eq!(BasicStruct::MAX.storage, BasicStruct::ONES.storage);
}
#[test]
fn struct_from_fields() {
let fields = BasicStructFields {
a: B3::new(5),
b: B5::new(20),
};
let val = BasicStruct::from_fields(fields);
assert_eq!(val.a(), B3::new(5));
assert_eq!(val.b(), B5::new(20));
}
#[test]
fn struct_to_fields() {
let val = BasicStruct::from_bits(0b10100_101);
let fields = val.to_fields();
assert_eq!(fields.a, B3::new(5));
assert_eq!(fields.b, B5::new(20));
}
#[test]
fn struct_fields_roundtrip() {
let original_fields = BasicStructFields {
a: B3::new(3),
b: B5::new(15),
};
let val = BasicStruct::from_fields(original_fields);
let extracted_fields = val.to_fields();
assert_eq!(original_fields, extracted_fields);
}
#[test]
fn struct_fields_into_from() {
let fields = BasicStructFields {
a: B3::new(5),
b: B5::new(20),
};
let val: BasicStruct = fields.into();
assert_eq!(val.a(), B3::new(5));
let fields2: BasicStructFields = val.into();
assert_eq!(fields2.a, B3::new(5));
}
#[test]
fn struct_const_eq() {
let a = BasicStruct::from_bits(0b10101_011);
let b = BasicStruct::from_bits(0b10101_011);
let c = BasicStruct::from_bits(0b10101_010);
assert!(BasicStruct::const_eq(a, b));
assert!(!BasicStruct::const_eq(a, c));
}
#[bitpiece(4, all)]
#[derive(Debug, PartialEq, Eq)]
struct StructWithBool {
flag: bool,
value: B3,
}
bitpiece_check_full_impl! {StructWithBool, true}
#[test]
fn struct_with_bool_field() {
let val = StructWithBool::from_bits(0b101_1);
assert_eq!(val.flag(), true);
assert_eq!(val.value(), B3::new(5));
let val = StructWithBool::from_bits(0b101_0);
assert_eq!(val.flag(), false);
assert_eq!(val.value(), B3::new(5));
}
#[test]
fn struct_with_bool_setters() {
let mut val = StructWithBool::ZEROES;
val.set_flag(true);
assert_eq!(val.flag(), true);
assert_eq!(val.storage, 0b000_1);
val.set_value(B3::new(7));
assert_eq!(val.value(), B3::new(7));
assert_eq!(val.storage, 0b111_1);
}
#[bitpiece(12, all)]
#[derive(Debug, PartialEq, Eq)]
struct StructWithSigned {
a: B3,
b: i8,
c: bool,
}
bitpiece_check_full_impl! {StructWithSigned, true}
#[test]
fn struct_with_signed_extraction() {
let raw = 0b1_11111111_101;
let val = StructWithSigned::from_bits(raw);
assert_eq!(val.a(), B3::new(5));
assert_eq!(val.b(), -1i8);
assert_eq!(val.c(), true);
}
#[test]
fn struct_with_signed_modification() {
let mut val = StructWithSigned::ZEROES;
val.set_b(-50);
assert_eq!(val.b(), -50i8);
val.set_b(100);
assert_eq!(val.b(), 100i8);
}
#[test]
fn struct_with_signed_min_max() {
let min = StructWithSigned::MIN;
assert_eq!(min.a(), B3::MIN);
assert_eq!(min.b(), i8::MIN);
assert_eq!(min.c(), bool::MIN);
let max = StructWithSigned::MAX;
assert_eq!(max.a(), B3::MAX);
assert_eq!(max.b(), i8::MAX);
assert_eq!(max.c(), bool::MAX);
}
#[bitpiece(16, all)]
#[derive(Debug, PartialEq, Eq)]
struct StructWithSb {
a: SB5,
b: bool,
c: SB7,
d: B3,
}
bitpiece_check_full_impl! {StructWithSb, true}
#[test]
fn struct_with_sb_extraction() {
let raw = 0b101_0101010_1_11111;
let val = StructWithSb::from_bits(raw);
assert_eq!(val.a(), SB5::new(-1));
assert_eq!(val.b(), true);
assert_eq!(val.c(), SB7::new(42));
assert_eq!(val.d(), B3::new(5));
}
#[test]
fn struct_with_sb_modification() {
let mut val = StructWithSb::ZEROES;
val.set_a(SB5::new(-5));
assert_eq!(val.a(), SB5::new(-5));
val.set_c(SB7::new(-30));
assert_eq!(val.c(), SB7::new(-30));
}
#[test]
fn struct_with_sb_from_to_fields() {
let fields = StructWithSbFields {
a: SB5::new(-10),
b: true,
c: SB7::new(55),
d: B3::new(6),
};
let val = StructWithSb::from_fields(fields);
assert_eq!(val.to_fields(), fields);
}
#[bitpiece(48, all)]
#[derive(Debug, PartialEq, Eq)]
struct StructWithIntegers {
byte: u8,
word: u16,
flags: B8,
signed: i16,
}
bitpiece_check_full_impl! {StructWithIntegers, true}
#[test]
fn struct_with_integers() {
let fields = StructWithIntegersFields {
byte: 0xAB,
word: 0xCDEF,
flags: B8::new(0x12),
signed: -1000,
};
let val = StructWithIntegers::from_fields(fields);
assert_eq!(val.byte(), 0xAB);
assert_eq!(val.word(), 0xCDEF);
assert_eq!(val.flags(), B8::new(0x12));
assert_eq!(val.signed(), -1000i16);
}
#[bitpiece(35, all)]
#[derive(Debug, PartialEq, Eq)]
struct LargeStruct {
x: u32,
y: B3,
}
bitpiece_check_full_impl! {LargeStruct, true}
#[test]
fn large_struct_storage_type() {
let _: u64 = LargeStruct::ZEROES.storage;
}
#[test]
fn large_struct_operations() {
let val = LargeStruct::from_bits(0b101_11111111111111111111111111111111);
assert_eq!(val.x(), 0xFFFFFFFF);
assert_eq!(val.y(), B3::new(5));
}
#[bitpiece(2, all)]
#[derive(Debug, PartialEq, Eq)]
enum Direction {
North = 0,
East = 1,
South = 2,
West = 3,
}
bitpiece_check_full_impl! {Direction, true}
#[bitpiece(5, all)]
#[derive(Debug, PartialEq, Eq)]
struct StructWithEnum {
dir: Direction,
speed: B3,
}
bitpiece_check_full_impl! {StructWithEnum, true}
#[test]
fn struct_with_enum_field() {
let val = StructWithEnum::from_bits(0b101_10);
assert_eq!(val.dir(), Direction::South);
assert_eq!(val.speed(), B3::new(5));
}
#[test]
fn struct_with_enum_setters() {
let mut val = StructWithEnum::ZEROES;
val.set_dir(Direction::West);
assert_eq!(val.dir(), Direction::West);
let val = val.with_speed(B3::new(7));
assert_eq!(val.speed(), B3::new(7));
}
#[test]
fn struct_field_mut() {
let mut val = BasicStruct::ZEROES;
{
let mut a_ref = val.a_mut();
assert_eq!(a_ref.get(), B3::new(0));
a_ref.set(B3::new(5));
}
assert_eq!(val.a(), B3::new(5));
}
#[test]
fn struct_field_mut_multiple() {
let mut val = BasicStruct::ZEROES;
{
let mut a_ref = val.a_mut();
a_ref.set(B3::new(3));
}
{
let mut b_ref = val.b_mut();
b_ref.set(B5::new(20));
}
assert_eq!(val.a(), B3::new(3));
assert_eq!(val.b(), B5::new(20));
}
#[test]
fn struct_clone_copy() {
let a = BasicStruct::from_bits(0b10101_011);
let b = a; let c = a.clone(); assert_eq!(a, b);
assert_eq!(a, c);
}
#[bitpiece(all)]
#[derive(Debug, PartialEq, Eq)]
enum SparseEnum {
A = 0,
B = 10,
C = 50,
}
bitpiece_check_full_impl! {SparseEnum, false}
#[bitpiece(9, all)]
#[derive(Debug, PartialEq, Eq)]
struct StructWithSparseEnum {
val: SparseEnum,
flag: bool,
extra: B2,
}
bitpiece_check_full_impl! {StructWithSparseEnum, false}
#[test]
fn struct_with_sparse_enum_valid() {
let val = StructWithSparseEnum::from_bits(0b01_1_001010);
assert_eq!(val.val(), SparseEnum::B);
assert_eq!(val.flag(), true);
assert_eq!(val.extra(), B2::new(1));
}
#[test]
fn struct_with_sparse_enum_try_from_bits() {
assert!(StructWithSparseEnum::try_from_bits(0b00_0_000000).is_some()); assert!(StructWithSparseEnum::try_from_bits(0b00_0_001010).is_some()); assert!(StructWithSparseEnum::try_from_bits(0b00_0_110010).is_some());
assert!(StructWithSparseEnum::try_from_bits(0b00_0_000001).is_none()); assert!(StructWithSparseEnum::try_from_bits(0b00_0_000101).is_none()); }
#[test]
fn struct_with_sparse_enum_from_bits_panics() {
expect_panic(|| {
let _ = StructWithSparseEnum::from_bits(0b00_0_000101); });
}
mod visibility_test {
use bitpiece::*;
#[bitpiece(8, all)]
#[derive(Debug, PartialEq, Eq)]
pub struct PublicStruct {
pub public_field: B4,
private_field: B4,
}
#[test]
fn public_struct_public_field() {
let val = PublicStruct::from_bits(0xFF);
assert_eq!(val.public_field(), B4::new(15));
}
}
#[bitpiece(8, all)]
#[derive(Debug, PartialEq, Eq, Hash)]
struct DerivedStruct {
a: B4,
b: B4,
}
#[test]
fn struct_derives_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(DerivedStruct::from_bits(0x12));
set.insert(DerivedStruct::from_bits(0x34));
set.insert(DerivedStruct::from_bits(0x12)); assert_eq!(set.len(), 2);
}
#[bitpiece(all)]
#[derive(Debug, PartialEq, Eq)]
struct AutoLenStruct {
a: B3,
b: B5,
c: bool,
}
bitpiece_check_full_impl! {AutoLenStruct, true}
#[test]
fn auto_len_struct() {
assert_eq!(AutoLenStruct::BITS, 9);
assert_eq!(AUTO_LEN_STRUCT_BIT_LEN, 9);
}
#[bitpiece(8, all)]
#[derive(Debug, PartialEq, Eq)]
struct Storage8 {
a: B8,
}
#[bitpiece(16, all)]
#[derive(Debug, PartialEq, Eq)]
struct Storage16 {
a: B16,
}
#[bitpiece(32, all)]
#[derive(Debug, PartialEq, Eq)]
struct Storage32 {
a: B32,
}
#[bitpiece(64, all)]
#[derive(Debug, PartialEq, Eq)]
struct Storage64 {
a: B64,
}
#[test]
fn storage_type_selection() {
let _: u8 = Storage8::ZEROES.storage;
let _: u16 = Storage16::ZEROES.storage;
let _: u32 = Storage32::ZEROES.storage;
let _: u64 = Storage64::ZEROES.storage;
}