Expand description
Packed struct encoding.
The packed_struct! macro declares a struct
whose fields are packed, most-significant-bit first, into a fixed number
of bytes, and implements Encode and
Decode for it. Each field names its width in bits:
use wire_codec::{packed_struct, Decode, Encode, ReadBuf, WriteBuf};
packed_struct! {
/// An IPv4 header's first 32 bits.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Ipv4Head {
pub version: u8 = 4,
pub ihl: u8 = 4,
pub dscp: u8 = 6,
pub ecn: u8 = 2,
pub total_length: u16 = 16,
}
}
assert_eq!(Ipv4Head::BITS, 32);
assert_eq!(Ipv4Head::SIZE, 4);
let head = Ipv4Head { version: 4, ihl: 5, dscp: 0, ecn: 0, total_length: 84 };
let mut out = [0u8; 4];
head.encode(&mut WriteBuf::new(&mut out)).unwrap();
assert_eq!(out, [0x45, 0x00, 0x00, 0x54]);
let decoded = Ipv4Head::decode(&mut ReadBuf::new(&out)).unwrap();
assert_eq!(decoded, head);§Field types
Any type implementing PackedField can be a field: all unsigned and
signed integers up to 64 bits (signed fields use two’s complement in their
declared width) and bool (one bit). Implement PackedField on your
own enums to pack them directly.
§Rules
- Field widths are checked at compile time: a width of
0, or wider than the field type (for exampleu8 = 9), is a compile error. - Encoding a value that does not fit its width returns
Error::BitOverflowand writes nothing. - When the total width is not a multiple of eight, the last byte is padded
with zero bits. Decoding rejects non-zero padding with
Error::InvalidEncoding, so every value has exactly one encoding. Declare reserved bits as an explicit field if a protocol lets them vary. - Decoding is atomic: on error the cursor does not move.
Traits§
- Packed
Field - A type that can be stored as a fixed-width bit field in a
packed_struct!.