module bitstruct_array_endian @test;
bitstruct BeLow : char[4] @bigendian { ushort a : 0..15; }
bitstruct LeLow : char[4] @littleendian { ushort a : 0..15; }
bitstruct BeMid : char[4] @bigendian { ushort a : 8..23; }
bitstruct LeMid : char[4] @littleendian { ushort a : 8..23; }
bitstruct Be12 : char[3] @bigendian { uint a : 0..11; }
bitstruct Le12 : char[3] @littleendian { uint a : 0..11; }
bitstruct Be15 : char[4] @bigendian { ushort a : 0..14; }
bitstruct Le15 : char[4] @littleendian { ushort a : 0..14; }
fn void test_byte_aligned_low_runtime()
{
BeLow be;
be.a = 0xABCD;
test::eq((char[4])be, x'ABCD0000');
assert(be.a == 0xABCD, "BE bits 0..15 round-trip: got %x", (uint)be.a);
LeLow le;
le.a = 0xABCD;
test::eq((char[4])le, x'CDAB0000');
assert(le.a == 0xABCD, "LE bits 0..15 round-trip: got %x", (uint)le.a);
}
fn void test_byte_aligned_mid_runtime()
{
BeMid be;
be.a = 0xABCD;
test::eq((char[4])be, x'00ABCD00');
assert(be.a == 0xABCD, "BE bits 8..23 round-trip: got %x", (uint)be.a);
LeMid le;
le.a = 0xABCD;
test::eq((char[4])le, x'00CDAB00');
assert(le.a == 0xABCD, "LE bits 8..23 round-trip: got %x", (uint)le.a);
}
fn void test_sub_byte_aligned_runtime()
{
Be12 be;
be.a = 0xABC;
test::eq((char[3])be, x'AB0C00');
assert(be.a == 0xABC, "BE 12-bit round-trip: got %x", (uint)be.a);
Le12 le;
le.a = 0xABC;
test::eq((char[3])le, x'BC0A00');
assert(le.a == 0xABC, "LE 12-bit round-trip: got %x", (uint)le.a);
}
fn void test_byte_aligned_low_const()
{
BeLow be = { .a = 0xABCD };
test::eq((char[4])be, x'ABCD0000');
BeLow be2 = { .a = 0x7869 };
test::eq((char[4])be2, x'78690000');
LeLow le = { .a = 0xABCD };
test::eq((char[4])le, x'CDAB0000');
LeLow le2 = { .a = 0x7869 };
test::eq((char[4])le2, x'69780000');
}
fn void test_byte_aligned_mid_const()
{
BeMid be = { .a = 0xABCD };
test::eq((char[4])be, x'00ABCD00');
LeMid le = { .a = 0xABCD };
test::eq((char[4])le, x'00CDAB00');
}
fn void test_sub_byte_aligned_const()
{
Be12 be = { .a = 0xABC };
test::eq((char[3])be, x'AB0C00');
Le12 le = { .a = 0xABC };
test::eq((char[3])le, x'BC0A00');
}
fn void test_15_bit_runtime()
{
// Field bits 0..14, value 0x7FFF.
Be15 be;
be.a = 0x7FFF;
test::eq((char[4])be, x'FF7F0000');
assert(be.a == 0x7FFF, "BE 15-bit round-trip: got %x", (uint)be.a);
Le15 le;
le.a = 0x7FFF;
test::eq((char[4])le, x'FF7F0000');
assert(le.a == 0x7FFF, "LE 15-bit round-trip: got %x", (uint)le.a);
}
fn void test_15_bit_const()
{
Be15 be = { .a = 0x7FFF };
test::eq((char[4])be, x'FF7F0000');
Le15 le = { .a = 0x7FFF };
test::eq((char[4])le, x'FF7F0000');
}
bitstruct NoSpill : char[2] @bigendian
{
ushort a : 0..14;
bool b : 15;
}
fn void test_no_spill_adjacent_field()
{
NoSpill f;
f.b = true;
assert(f.b, "b should be true after assignment");
test::eq((char[2])f, x'0080');
// Writing `a` must leave `b` alone.
f.a = 0;
assert(f.b, "b corrupted by writing a = 0");
test::eq((char[2])f, x'0080');
f.a = 0x7FFF;
assert(f.b, "b corrupted by writing a = 0x7FFF");
test::eq((char[2])f, x'FFFF');
f.a = 0x1234;
assert(f.b, "b corrupted by writing a = 0x1234");
// And `b = false` must leave `a` alone.
f.a = 0x7FFF;
f.b = false;
assert(!f.b, "b not cleared");
assert(f.a == 0x7FFF, "a corrupted by writing b = false: got %x", (uint)f.a);
}