1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! **bitfield_bytes** — a `#[bitfield]`'s declared byte order (`bytes = big|le`) drives
//! `to_bytes()`/`from_bytes()`, while `to_be_bytes`/`to_le_bytes` are the explicit override.
//!
//! The *same* logical value, declared big- vs little-endian, serializes to *different* wire bytes
//! through `to_bytes()` — the order-respecting path. The endianness-explicit methods ignore the
//! declaration; reach for them only to force a specific order regardless of how the type was
//! declared.
//!
//! Run with: `cargo run -p bitsandbytes --example bitfield_bytes`
use bnb::{bitfield, u4};
/// A 16-bit field packed MSB-first, declared **big-endian**.
#[bitfield(u16, bits = msb, bytes = big)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct TagBe {
hi: u4,
mid: u8,
lo: u4,
}
/// The same fields, declared **little-endian**.
#[bitfield(u16, bits = msb, bytes = little)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct TagLe {
hi: u4,
mid: u8,
lo: u4,
}
fn main() {
let be = TagBe::new()
.with_hi(u4::new(0xA))
.with_mid(0xBC)
.with_lo(u4::new(0xD));
let le = TagLe::new()
.with_hi(u4::new(0xA))
.with_mid(0xBC)
.with_lo(u4::new(0xD));
// Same logical value (raw = 0xABCD), packed identically (both MSB-first)...
assert_eq!(be.to_raw(), 0xABCD);
assert_eq!(le.to_raw(), 0xABCD);
// ...but `to_bytes()` serializes in each type's DECLARED byte order:
assert_eq!(be.to_bytes(), [0xAB, 0xCD]); // big-endian
assert_eq!(le.to_bytes(), [0xCD, 0xAB]); // little-endian
println!(
"to_bytes() honors the declaration: be -> {:02X?}, le -> {:02X?}",
be.to_bytes(),
le.to_bytes()
);
// `from_bytes()` is the inverse, also in the declared order — a clean round-trip:
assert_eq!(TagBe::from_bytes(be.to_bytes()), be);
assert_eq!(TagLe::from_bytes(le.to_bytes()), le);
// The endianness-explicit methods IGNORE the declaration — use them only to override:
assert_eq!(le.to_be_bytes(), [0xAB, 0xCD]); // force big, though declared little
assert_eq!(be.to_le_bytes(), [0xCD, 0xAB]); // force little, though declared big
println!("to_be_bytes/to_le_bytes override the declaration (explicit endianness)");
println!("all checks passed");
}