Skip to main content

Module packed

Module packed 

Source
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 example u8 = 9), is a compile error.
  • Encoding a value that does not fit its width returns Error::BitOverflow and 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§

PackedField
A type that can be stored as a fixed-width bit field in a packed_struct!.