De-Serializing

The de-serialization of a byte stream by a byte stream mapper is not considered independent from the reading of the byte stream.

Therefore the deserialize() method of the byte stream mapper is not called directly during the de-serialization process. The deserialize() method is called by the pointer during the reading of the byte stream where the byte stream mapper is attached to.

De-Serializing Hook

The deserialize() method which every field and container has allows to hook in the reading/de-serialization process at a certain point of the byte stream to adapt the byte stream mapper and to control the reading of the byte stream by the providing pointer.

>>> class OPCString(Structure):
...
...     def __init__(self):
...         super().__init__()
...         # Length of the string
...         self.length = Decimal16()
...         # Content of the string
...         self.content = String()
...         self.index_fields()
...
...     def deserialize(self, buffer=bytes(), index=Index(), **options):
...         # Deserialize length field first.
...         index = self.length.deserialize(buffer, index, **options)
...         # Check if content field size is incorrect.
...         if int(self.length) != len(self.content):
...             # Re-size content field on the fly.
...             self.content.resize(int(self.length))
...             # Deserialize content field with new size.
...             index = self.content.deserialize(buffer, index, **options)
...             # Request a buffer update from the providing pointer on the fly.
...             # note: Starts the deserialization for the byte stream mapper again.
...             return index._replace(update=True)
...         else:
...             # Deserialize content field with correct size.
...             return self.content.deserialize(buffer, index, **options)
>>> # Create an instance of the empty OPC string
>>> string = OPCString()
>>> # List the field values of the OPC string.
>>> string.to_list()
[('OPCString.length', 0),
 ('OPCString.content', '')]
>>> # List the field values of the OPC string as a CSV list.
>>> string.to_csv()
[{'id': 'OPCString.length', 'value': 0},
 {'id': 'OPCString.content', 'value': ''}]
>>> # View the OPC string field values as a JSON string.
>>> string.to_json()
'{"length": 0, "content": ""}'
>>> # Size of the OPC string.
>>> string.container_size()
(2, 0)
>>> # Deserialize the empty OPC string
>>> string.deserialize(bytes.fromhex('0f004b6f6e466f6f206973202746756e27'))
Index(byte=17, bit=0, address=17, base_address=0, update=True)
>>> # Size of the OPC string.
>>> string.container_size()
(17, 0)
>>> # Deserialize the filled OPC string
>>> string.deserialize(bytes.fromhex('0f004b6f6e466f6f206973202746756e27'))
Index(byte=17, bit=0, address=17, base_address=0, update=False)
>>> # Size of the OPC string.
>>> string.container_size()
(17, 0)
>>> # List the field values of the OPC string.
>>> string.to_list()
[('OPCString.length', 15),
 ('OPCString.content', "KonFoo is 'Fun'")]
>>> # List the field values of the OPC string as a CSV list.
>>> string.to_csv()
[{'id': 'OPCString.length', 'value': 15},
 {'id': 'OPCString.content', 'value': "KonFoo is 'Fun'"}]
>>> # View the OPC string field values as a JSON string.
>>> string.to_json()
'{"length": 15, "content": "KonFoo is \'Fun\'"}'