Structure#

KonFoo has a Structure class and many field classes to declare the mapping part of a byte stream mapper.

The order how you declare the members in the structure defines the order how the members are deserialized and serialized by the built-in deserializer and serializer.

Member#

A structure member can be any field or container class.

Define a Structure#

You can define members of a structure by adding them in the constructor method of the Structure class.

>>> class Identifier(Structure):
...
...     def __init__(self):
...         super().__init__()        # <- NEVER forget to call it first!
...         self.version = Byte()     # 1st field
...         self.id = Unsigned8()     # 2nd field
...         self.length = Decimal8()  # 3rd field
...         self.module = Char()      # 4th field
...         self.index_fields()       # <- Indexes all fields (optional)
>>> # Create an instance of the structure.
>>> identifier = Identifier()
>>> # List the field values of the structure.
>>> identifier.to_list()
[('Identifier.version', '0x0'),
 ('Identifier.id', '0x0'),
 ('Identifier.length', 0),
 ('Identifier.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> identifier.to_csv()
[{'id': 'Identifier.version', 'value': '0x0'},
 {'id': 'Identifier.id', 'value': '0x0'},
 {'id': 'Identifier.length', 'value': 0},
 {'id': 'Identifier.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> identifier.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'

Warning

A structure must always align to full bytes or an exception will be raised when an incomplete structure declaration is deserialized or serialized.

Align Fields in a Structure#

You can align consecutive fields in a structure to each other by using the align_to parameter of the Field class.

>>> class Identifier(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.version = Byte(align_to=4)       # 1st field aligned to 4 bytes
...         self.id = Unsigned(8, align_to=4)     # 2nd field aligned to 4 bytes
...         self.length = Decimal(8, align_to=4)  # 3rd field aligned to 4 bytes
...         self.module = Char(align_to=4)        # 4th field aligned to 4 bytes
...         self.index_fields()
>>> # Create an instance of the structure.
>>> identifier = Identifier()
>>> # List the field alignments of the structure.
>>> identifier.to_list('alignment')
[('Identifier.version', Alignment(byte_size=4, bit_offset=0)),
 ('Identifier.id', Alignment(byte_size=4, bit_offset=8)),
 ('Identifier.length', Alignment(byte_size=4, bit_offset=16)),
 ('Identifier.module', Alignment(byte_size=4, bit_offset=24))]
>>> # List the field alignments of the structure as a CSV list.
>>> identifier.to_csv('alignment.byte_size', 'alignment.bit_offset')
[{'id': 'Identifier.version', 'alignment.byte_size': 4, 'alignment.bit_offset': 0},
 {'id': 'Identifier.id', 'alignment.byte_size': 4, 'alignment.bit_offset': 8},
 {'id': 'Identifier.length', 'alignment.byte_size': 4, 'alignment.bit_offset': 16},
 {'id': 'Identifier.module', 'alignment.byte_size': 4, 'alignment.bit_offset': 24}]
>>> # View the structure field alignments as a JSON string.
>>> identifier.to_json('alignment')
'{"version": [4, 0], "id": [4, 8], "length": [4, 16], "module": [4, 24]}'

Note

The field alignment works only for the Decimal field classes.

Nest Structures#

You can nest a structure in another structure.

>>> # Define a new structure class with a nested structure.
>>> class Header(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.type = Identifier()  # nested structure
...         self.size = Decimal32()
...         self.index_fields()
>>> # Create an instance of the structure.
>>> header = Header()
>>> # List the field values of the structure.
>>> header.to_list()
[('Header.type.version', '0x0'),
 ('Header.type.id', '0x0'),
 ('Header.type.length', 0),
 ('Header.type.module', '\x00'),
 ('Header.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> header.to_csv()
[{'id': 'Header.type.version', 'value': '0x0'},
 {'id': 'Header.type.id', 'value': '0x0'},
 {'id': 'Header.type.length', 'value': 0},
 {'id': 'Header.type.module', 'value': '\x00'},
 {'id': 'Header.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> header.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

Inherit from a Structure#

You can inherit the members from a structure class to extend or change it.

>>> # Define a new structure class.
>>> class HeaderV1(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.type = Identifier()
...         self.index_fields()
>>> # Create an instance of the structure.
>>> header = HeaderV1()
>>> # List the field values of the structure.
>>> header.to_list()
[('HeaderV1.type.version', '0x0'),
 ('HeaderV1.type.id', '0x0'),
 ('HeaderV1.type.length', 0),
 ('HeaderV1.type.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> header.to_csv()
[{'id': 'HeaderV1.type.version', 'value': '0x0'},
 {'id': 'HeaderV1.type.id', 'value': '0x0'},
 {'id': 'HeaderV1.type.length', 'value': 0},
 {'id': 'HeaderV1.type.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> header.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}}'
>>> # Define a new structure class inherit from a structure the fields.
>>> class HeaderV2(HeaderV1):
...
...     def __init__(self):
...         super().__init__()
...         self.size = Decimal32()
...         self.index_fields()
>>> # Create an instance of the structure.
>>> header = HeaderV2()
>>> # List the field values of the structure.
>>> header.to_list()
[('HeaderV2.type.version', '0x0'),
 ('HeaderV2.type.id', '0x0'),
 ('HeaderV2.type.length', 0),
 ('HeaderV2.type.module', '\x00'),
 ('HeaderV2.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> header.to_csv()
[{'id': 'HeaderV2.type.version', 'value': '0x0'},
 {'id': 'HeaderV2.type.id', 'value': '0x0'},
 {'id': 'HeaderV2.type.length', 'value': 0},
 {'id': 'HeaderV2.type.module', 'value': '\x00'},
 {'id': 'HeaderV2.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> header.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

Declare on the fly#

You can declare a structure on the fly.

>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add fields to the structure.
>>> structure.version = Byte()
>>> structure.id = Unsigned8()
>>> structure.length = Decimal8()
>>> structure.module = Char()
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x0'),
 ('Structure.id', '0x0'),
 ('Structure.length', 0),
 ('Structure.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x0'},
 {'id': 'Structure.id', 'value': '0x0'},
 {'id': 'Structure.length', 'value': 0},
 {'id': 'Structure.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'

You can declare a structure with aligned fields on the fly.

>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add aligned fields to the structure.
>>> structure.version = Byte(4)
>>> structure.id = Unsigned(8, 4)
>>> structure.length = Decimal(8, 4)
>>> structure.module = Char(4)
>>> # Index the fields in the structure.
>>> structure.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field alignments of the structure.
>>> structure.to_list('alignment')
[('Structure.version', Alignment(byte_size=4, bit_offset=0)),
 ('Structure.id', Alignment(byte_size=4, bit_offset=8)),
 ('Structure.length', Alignment(byte_size=4, bit_offset=16)),
 ('Structure.module', Alignment(byte_size=4, bit_offset=24))]
>>> # List the field alignments of the structure as a CSV list.
>>> structure.to_csv('alignment.byte_size', 'alignment.bit_offset')
[{'id': 'Structure.version', 'alignment.byte_size': 4, 'alignment.bit_offset': 0},
 {'id': 'Structure.id', 'alignment.byte_size': 4, 'alignment.bit_offset': 8},
 {'id': 'Structure.length', 'alignment.byte_size': 4, 'alignment.bit_offset': 16},
 {'id': 'Structure.module', 'alignment.byte_size': 4, 'alignment.bit_offset': 24}]
>>> # View the structure field alignments as a JSON string.
>>> structure.to_json('alignment')
'{"version": [4, 0], "id": [4, 8], "length": [4, 16], "module": [4, 24]}'

You can declare a structure with keywords.

>>> # Create a structure with keywords.
>>> structure = Structure(
...     version=Byte(4),
...     id=Unsigned(8, 4),
...     length=Decimal(8, 4),
...     module=Char(4))
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x0'),
 ('Structure.id', '0x0'),
 ('Structure.length', 0),
 ('Structure.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x0'},
 {'id': 'Structure.id', 'value': '0x0'},
 {'id': 'Structure.length', 'value': 0},
 {'id': 'Structure.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'

You can nest structure’s on the fly.

>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add an empty nested structure to the structure.
>>> structure.type = Structure()
>>> # Add fields to the nested structure.
>>> structure.type.version = Byte(4)
>>> structure.type.id = Unsigned(8, 4)
>>> structure.type.length = Decimal(8, 4)
>>> structure.type.module = Char(4)
>>> # Add a field to the structure.
>>> structure.size = Decimal32()
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.type.version', '0x0'),
 ('Structure.type.id', '0x0'),
 ('Structure.type.length', 0),
 ('Structure.type.module', '\x00'),
 ('Structure.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.type.version', 'value': '0x0'},
 {'id': 'Structure.type.id', 'value': '0x0'},
 {'id': 'Structure.type.length', 'value': 0},
 {'id': 'Structure.type.module', 'value': '\x00'},
 {'id': 'Structure.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

You can assign a structure to a member of another structure on the fly.

>>> # Create a structure to be nested.
>>> identifier = Structure(
...     version = Byte(4),
...     id = Unsigned(8, 4),
...     length = Decimal(8, 4),
...     module = Char(4))
>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add a nested structure to the structure.
>>> structure.type = identifier
>>> # Add a field to the structure.
>>> structure.size = Decimal32()
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.type.version', '0x0'),
 ('Structure.type.id', '0x0'),
 ('Structure.type.length', 0),
 ('Structure.type.module', '\x00'),
 ('Structure.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.type.version', 'value': '0x0'},
 {'id': 'Structure.type.id', 'value': '0x0'},
 {'id': 'Structure.type.length', 'value': 0},
 {'id': 'Structure.type.module', 'value': '\x00'},
 {'id': 'Structure.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

Initialize a Structure#

You can initialize the fields in a structure by calling the method initialize_fields().

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(4),
...     id=Unsigned(8, 4),
...     length=Decimal(8, 4),
...     module=Char(4))
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x0'),
 ('Structure.id', '0x0'),
 ('Structure.length', 0),
 ('Structure.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x0'},
 {'id': 'Structure.id', 'value': '0x0'},
 {'id': 'Structure.length', 'value': 0},
 {'id': 'Structure.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'
>>> # Initialize the fields of the structure.
>>> structure.initialize_fields(
...     dict(version=1, id=2, length=9, module=0x46))
>>> # Initialize the fields in the structure.
>>> structure.initialize_fields({
...     "version": "0x1",
...     "id": "0x2",
...     "length": 9,
...     "module": "F"
... })
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x1", "id": "0x2", "length": 9, "module": "F"}'

Display a Structure#

You can display the structure.

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(4),
...     id=Unsigned(8, 4),
...     length=Decimal(8, 4),
...     module=Char(4))
>>> # Index the fields in the structure.
>>> structure.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Display the structure.
>>> structure  
{'version': Byte(
    index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
    alignment=Alignment(byte_size=4, bit_offset=0),
    bit_size=8,
    value='0x0'),
 'id': Unsigned(
    index=Index(byte=0, bit=8, address=0, base_address=0, update=False),
    alignment=Alignment(byte_size=4, bit_offset=8),
    bit_size=8,
    value='0x0'),
 'length': Decimal(
    index=Index(byte=0, bit=16, address=0, base_address=0, update=False),
    alignment=Alignment(byte_size=4, bit_offset=16),
    bit_size=8,
    value=0),
 'module': Char(
    index=Index(byte=0, bit=24, address=0, base_address=0, update=False),
    alignment=Alignment(byte_size=4, bit_offset=24),
    bit_size=8,
    value='\x00')}

Metadata of a Structure#

You can get the metadata of the structure by calling the method describe().

A dict with the metadata of the structure is returned.

>>> # Get the metadata of the structure.
>>> structure.describe()  
{'class': 'Structure',
 'name': 'Structure',
 'size': 4,
 'type': 'Structure',
 'member': [
    {'address': 0,
     'alignment': [4, 0],
     'class': 'Byte',
     'index': [0, 0],
     'max': 255,
     'min': 0,
     'name': 'version',
     'order': 'auto',
     'signed': False,
     'size': 8,
     'type': 'Field',
     'value': '0x0'},
    {'address': 0,
     'alignment': [4, 8],
     'class': 'Unsigned8',
     'index': [0, 8],
     'max': 255,
     'min': 0,
     'name': 'id',
     'order': 'auto',
     'signed': False,
     'size': 8, 'type':
     'Field',
     'value': '0x0'},
    {'address': 0,
     'alignment': [4, 16],
     'class': 'Decimal8',
     'index': [0, 16],
     'max': 255,
     'min': 0,
     'name': 'length',
     'order': 'auto',
     'signed': False,
     'size': 8, 'type':
     'Field',
     'value': 0},
    {'address': 0,
     'alignment': [4, 24],
     'class': 'Char',
     'index': [0, 24],
     'max': 255,
     'min': 0,
     'name': 'module',
     'order': 'auto',
     'signed': False,
     'size': 8,
     'type': 'Field',
     'value': '\x00'}]
}
>>> # Dump the metadata of the structure as a JSON string to the console.
>>> json.dump(structure.describe(), sys.stdout, indent=2)
{
  "class": "Structure",
  "name": "Structure",
  "size": 4,
  "type": "Structure",
  "member": [
    {
      "address": 0,
      "alignment": [
        4,
        0
      ],
      "class": "Byte",
      "index": [
        0,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "version",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 0,
      "alignment": [
        4,
        8
      ],
      "class": "Unsigned8",
      "index": [
        0,
        8
      ],
      "max": 255,
      "min": 0,
      "name": "id",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 0,
      "alignment": [
        4,
        16
      ],
      "class": "Decimal8",
      "index": [
        0,
        16
      ],
      "max": 255,
      "min": 0,
      "name": "length",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": 0
    },
    {
      "address": 0,
      "alignment": [
        4,
        24
      ],
      "class": "Char",
      "index": [
        0,
        24
      ],
      "max": 255,
      "min": 0,
      "name": "module",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "\u0000"
    }
  ]
}

Size of a Structure#

You can get the size of a structure as a tuple in the form of (number of bytes, number of remaining bits) by calling the method container_size().

>>> # Get the size of the structure.
>>> structure.container_size()
(4, 0)

Note

The number of remaining bits must be always zero or the structure declaration is incomplete.

Indexing#

You can index all fields in a structure by calling the method index_fields().

The Index after the last field of the structure is returned.

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(),
...     id=Unsigned8(),
...     length=Decimal8(),
...     module=Char())
>>> # List the field indexes of the structure.
>>> structure.to_list('index')
[('Structure.version', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.id', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.length', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.module', Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the structure as a CSV list.
>>> structure.to_csv('index.byte', 'index.address')
[{'id': 'Structure.version', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.id', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.length', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.module', 'index.byte': 0, 'index.address': 0}]
>>> # View the structure field indexes as a JSON string.
>>> structure.to_json('index')
'{"version": [0, 0, 0, 0, false],
  "id":      [0, 0, 0, 0, false],
  "length":  [0, 0, 0, 0, false],
  "module":  [0, 0, 0, 0, false]}'
>>> # Index the fields in the structure.
>>> structure.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Index the fields in the structure with a start index.
>>> structure.index_fields(index=Index())
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field indexes of the structure.
>>> structure.to_list('index')
[('Structure.version', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.id', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Structure.length', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Structure.module', Index(byte=3, bit=0, address=3, base_address=0, update=False))]
>>> # List the field indexes of the structure as a CSV list.
>>> structure.to_csv('index.byte', 'index.address')
[{'id': 'Structure.version', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.id', 'index.byte': 1, 'index.address': 1},
 {'id': 'Structure.length', 'index.byte': 2, 'index.address': 2},
 {'id': 'Structure.module', 'index.byte': 3, 'index.address': 3}]
>>> # View the structure field indexes as a JSON string.
>>> structure.to_json('index')
'{"version": [0, 0, 0, 0, false],
  "id":      [1, 0, 1, 0, false],
  "length":  [2, 0, 2, 0, false],
  "module":  [3, 0, 3, 0, false]}'

De-Serializing#

You can deserialize a byte stream with a structure by calling the method deserialize().

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(),
...     id=Unsigned8(),
...     length=Decimal8(),
...     module=Char())
>>> # Create a byte stream to be deserialized.
>>> bytestream = bytes.fromhex('01020946f00f00')
>>> # Deserialize the byte stream and map it to the structure.
>>> structure.deserialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x1", "id": "0x2", "length": 9, "module": "F"}'

Serializing#

You can serialize a byte stream with a structure by calling the method serialize().

>>> # Create an empty byte stream.
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> # Serialize the structure to the byte stream.
>>> structure.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Display the byte stream.
>>> bytestream.hex()
'01020946'

or

>>> bytes(structure).hex()
'01020946'

Number of Members#

You can get the number of structure members with the built-in function len().

>>> # Number of structure members.
>>> len(structure)
4

Access a Member#

You can access a structure member with its name.

>>> # Access a structure member with its attribute name.
>>> structure.version
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x1')
>>> # Access a structure member with its key name.
>>> structure['version']
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x1')

Attributes of a Member Field#

You can access the Field attributes of a field member in a structure with the attribute names:

>>> # Field name.
>>> structure.version.name
'Byte'
>>> # Field value.
>>> structure.version.value
'0x1'
>>> # Field bit size.
>>> structure.version.bit_size
8
>>> # Field alignment.
>>> structure.version.alignment
Alignment(byte_size=1, bit_offset=0)
>>> # Field alignment: byte size of the aligned field group.
>>> structure.version.alignment.byte_size
1
>>> # Field alignment: bit offset of the field in its field group.
>>> structure.version.alignment.bit_offset
0
>>> # Field byte order.
>>> structure.version.byte_order
Byteorder.auto = 'auto'
>>> # Field byte order value.
>>> structure.version.byte_order.value
'auto'
>>> # Field index.
>>> structure.version.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> # Field index: byte offset of the field in the byte stream.
>>> structure.version.index.byte
0
>>> # Field index: bit offset of the field relative to its byte offset.
>>> structure.version.index.bit
0
>>> # Field index: memory address of the field in the data source.
>>> structure.version.index.address
0
>>> # Field index: start address of the byte stream in the data source.
>>> structure.version.index.base_address
0
>>> # Field index: update request for the byte stream.
>>> structure.version.index.update
False

You can check if a structure member is a field.

>>> is_field(structure.version)
True

You can check what kind of field it is.

>>> # Field is a bit field.
>>> structure.version.is_bit()
False
>>> # Field is a boolean field.
>>> structure.version.is_bool()
False
>>> # Field is a decimal field.
>>> structure.version.is_decimal()
True
>>> # Field is a float field.
>>> structure.version.is_float()
False
>>> # Field is a pointer field.
>>> structure.version.is_pointer()
False
>>> # Field is a stream field.
>>> structure.version.is_stream()
False
>>> # Field is a string field.
>>> structure.version.is_string()
False

Iterate over Members#

You can iterate over the structure member names.

>>> [name for name in structure.keys()]
['version', 'id', 'length', 'module']

You can iterate over all kind of member items of a structure.

>>> [(name, member.item_type) for name, member in structure.items()]
[('version', ItemClass.Byte = 42),
 ('id', ItemClass.Unsigned = 45),
 ('length', ItemClass.Decimal = 40),
 ('module', ItemClass.Char = 43)]

You can iterate over all kind of members of a structure.

>>> [member.item_type for member in structure.values()]
[ItemClass.Byte = 42,
 ItemClass.Unsigned = 45,
 ItemClass.Decimal = 40,
 ItemClass.Char = 43]

You can iterate over all field members of a structure.

>>> [member.name for member in structure.values() if is_field(member)]
['Byte', 'Unsigned8', 'Decimal8', 'Char']

View Field Attributes#

You can view the attributes of each field of a structure as a dictionary by calling the method view_fields().

The default attribute is the field value.

>>> # View the structure field values.
>>> structure.view_fields()
{'version': '0x1',
 'id': '0x2',
 'length': 9,
 'module': 'F'}
>>> # View the structure field type names & field values.
>>> structure.view_fields('name', 'value')
{'version': {'name': 'Byte', 'value': '0x1'},
 'id': {'name': 'Unsigned8', 'value': '0x2'},
 'length': {'name': 'Decimal8', 'value': 9},
 'module': {'name': 'Char', 'value': 'F'}}
>>> # View the structure field indexes.
>>> structure.view_fields('index')
{'version': Index(byte=0, bit=0, address=0, base_address=0, update=False),
 'id': Index(byte=1, bit=0, address=1, base_address=0, update=False),
 'length': Index(byte=2, bit=0, address=2, base_address=0, update=False),
 'module': Index(byte=3, bit=0, address=3, base_address=0, update=False)}

Note

The attributes of each field for containers nested in the structure are viewed as well (chained method call).

View as a JSON string#

You can view the attributes of each field of a structure as a JSON formatted string by calling the method to_json().

The default attribute is the field value.

>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x1", "id": "0x2", "length": 9, "module": "F"}'
>>> print(structure.to_json(indent=2))
{
  "version": "0x1",
  "id": "0x2",
  "length": 9,
  "module": "F"
}
>>> # View the structure field type names & field values as a JSON string.
>>> structure.to_json('name', 'value')
'{"version": {"name": "Byte", "value": "0x1"},
  "id": {"name": "Unsigned8", "value": "0x2"},
  "length": {"name": "Decimal8", "value": 9},
  "module": {"name": "Char", "value": "F"}}'
>>> # View the structure field indexes as a JSON string.
>>> structure.to_json('index')
'{"version": [0, 0, 0, 0, false],
  "id": [1, 0, 1, 0, false],
  "length": [2, 0, 2, 0, false],
  "module": [3, 0, 3, 0, false]}'

Note

The attributes of each field for containers nested in the structure are viewed as well (chained method call).

List Field Items#

You can list all field items of a structure as a flatten list by calling the method field_items().

>>> # List the field items of the structure.
>>> structure.field_items()
[('version',
 Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x1')),
('id',
 Unsigned8(index=Index(byte=1, bit=0, address=1, base_address=0, update=False),
           alignment=Alignment(byte_size=1, bit_offset=0),
           bit_size=8,
           value='0x2')),
('length',
 Decimal8(index=Index(byte=2, bit=0, address=2, base_address=0, update=False),
          alignment=Alignment(byte_size=1, bit_offset=0),
          bit_size=8,
          value=9)),
('module',
 Char(index=Index(byte=3, bit=0, address=3, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='F'))]

List Field Attributes#

You can list the attributes of each field of a structure as a flatten list by calling the method to_list().

The default attribute is the field value.

>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # List the field type names & values of the structure.
>>> structure.to_list('name', 'value')
[('Structure.version', ('Byte', '0x1')),
 ('Structure.id', ('Unsigned8', '0x2')),
 ('Structure.length', ('Decimal8', 9)),
 ('Structure.module', ('Char', 'F'))]
>>> # List the field indexes of the structure.
>>> structure.to_list('index')
[('Structure.version', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.id', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Structure.length', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Structure.module', Index(byte=3, bit=0, address=3, base_address=0, update=False))]

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a structure as a flatten dictionary by calling the method to_dict().

The default attribute is the field value.

>>> # List the field values of the structure.
>>> structure.to_dict()
{'Structure': {'version': '0x1', 'id': '0x2', 'length': 9, 'module': 'F'}}
>>> # List the field type names & values of the structure.
>>> structure.to_dict('name', 'value')  
{'Structure': {
 'version': ('Byte', '0x1'),
 'id': ('Unsigned8', '0x2'),
 'length': ('Decimal8', 9),
 'module': ('Char', 'F')}
}
>>> # List the field indexes in the structure.
>>> structure.to_dict('index')  
{'Structure': {
 'version': Index(byte=0, bit=0, address=0, base_address=0, update=False),
 'id': Index(byte=1, bit=0,address=1, base_address=0, update=False),
 'length': Index(byte=2, bit=0, address=2, base_address=0, update=False),
 'module', Index(byte=3, bit=0, address=3, base_address=0, update=False)}
}

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a structure as a flatten list of dictionaries containing the field path and the selected field attributes by calling the method to_csv().

The default attribute is the field value.

>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # List the field type names & values of the structure as a CSV list.
>>> structure.to_csv('name', 'value')
[{'id': 'Structure.version', 'name': 'Byte', 'value': '0x1'},
 {'id': 'Structure.id', 'name': 'Unsigned8', 'value': '0x2'},
 {'id': 'Structure.length', 'name': 'Decimal8', 'value': 9},
 {'id': 'Structure.module', 'name': 'Char', 'value': 'F'}]

Note

The class name of the instance is used for the root name as long as no name is given.

Write Field Attributes#

You can write the attributes of each field of a structure to a .csv file by calling the method write_csv().

The default attribute is the field value.

>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # Save the structure field values to a '.csv' file.
>>> structure.write_csv("./_static/structure.csv")

The generated .csv file for the structure looks like this:

id,value
Structure.version,0x1
Structure.id,0x2
Structure.length,9
Structure.module,F

Note

The class name of the instance is used for the root name as long as no name is given.

Save Field Attributes#

You can save the attributes of each field of a structure to an .ini file by calling the method save().

The default attribute is the field value.

>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # Save the structure field values to an '.ini' file.
>>> structure.save("./_static/structure.ini")

The generated .ini file for the structure looks like this:

[Structure]
version = 0x1
id = 0x2
length = 9
module = F

Note

The class name of the instance is used for the section name as long as no section is given.

Load Field Values#

You can load the value of each field of a structure from an .ini file by calling the method load().

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(),
...     id=Unsigned8(),
...     length=Decimal8(),
...     module=Char())
>>> # Load the structure field values from an '.ini' file.
>>> structure.load("./_static/structure.ini")
[Structure]
Structure.version = 0x1
Structure.id = 0x2
Structure.length = 9
Structure.module = F
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]

Note

The class name of the instance is used for the section name as long as no section is given.