[plum] Structure Tutorial: Embedded Bit Field Members¶
This tutorial shows how to use the Member
and BitFieldMember
member definition classes within a structure definition and the differences
between them.
Nested¶
The following shows use of the standard Member
member definition
to include the nibble1
and nibble2
bitfields within the structure.
In the example, the Sample
structure “nests” the bit fields within
the nibbles
member.
>>> from plum.int.bitfields import BitField, BitFields
>>> from plum.int.little import UInt8
>>> from plum.structure import Structure, Member
>>>
>>> class TwoNibbles(BitFields, nbytes=1):
... nibble1: int = BitField(pos=0, size=4)
... nibble2: int = BitField(pos=4, size=4)
...
>>> class Sample(Structure):
... nibbles: int = Member(cls=TwoNibbles)
... byte: int = Member(cls=UInt8)
...
The structure instantiation accepts a value for nibbles
rather than the
individual bit fields. Access to the bit fields goes through the nibbles
member as well:
>>> sample = Sample(nibbles=TwoNibbles(0x21), byte=0xff)
>>> sample.nibbles.nibble1
1
>>> sample.nibbles.nibble2
2
Flattened¶
The following shows use of the BitFieldMember
member definition
to include the nibble1
and nibble2
bit fields directly within the
structure.
>>> from plum.int.bitfields import BitField, BitFields
>>> from plum.int.little import UInt8
>>> from plum.structure import Structure, BitFieldMember
>>>
>>> class TwoNibbles(BitFields, nbytes=1):
... nibble1: int = BitField(pos=0, size=4)
... nibble2: int = BitField(pos=4, size=4)
...
>>> class Sample(Structure):
... nibble1: int = BitFieldMember(cls=TwoNibbles)
... nibble2: int = BitFieldMember(cls=TwoNibbles, default=2)
... byte: int = Member(cls=UInt8)
...
Direct inclusion of the bit fields within the structure causes the instantiation to accept values for each of the bit fields instead of one value for them all. It also allows direct access from the structure:
>>> sample = Sample(nibble1=1, nibble2=2, byte=0xff)
>>> sample.nibble1
1
>>> sample.nibble2
2
As shown for nibble2
, the BitFieldMember
accepts a default value for
a bit field that may differ from those specified in the TwoNibbles
bit fields
collection. This allows the bit field value to be skipped when instantiating or packing:
>>> sample = Sample(nibble1=1, byte=0xff)
>>> sample.pack().hex()
'21ff'
>>>
>>> Sample.pack({'nibble1': 1, 'byte': 0xff}).hex()
'21ff'
Defining the bit fields directly within the structure only changes the instantiation
and access as described. The core members of the structure itself remain the same
(the bitfields are contained within the same [0]
member):
>>> sample = Sample(nibble1=1, nibble2=2, byte=0xff)
>>> sample[0]
TwoNibbles(nibble1=1, nibble2=2)