Delimited serialization example

Here is an example of delimited serialization in action. I wrote it while working on the serialization test suite for PyUAVCAN, which you can find under tests/dsdl/.

You can reproduce this locally to understand how it works using PyUAVCAN in REPL or in Jupyter.

Serializing A.1.0

DSDL definitions

# A.1.0
@union
BSealed.1.0    sea
BDelimited.1.0 del
@extent 56 * 8
# BSealed.1.0
CVariable.1.0[<=2] var
CFixed.1.0[<=2]    fix
@sealed
# BDelimited.1.0
CVariable.1.0[<=2] var
CFixed.1.0[<=2]    fix
@extent 40 * 8
# CVariable.1.0
uint8[<=2] a
int8 b
@extent 4 * 8
# CFixed.1.0
uint8[2] a
@extent 4 * 8

Instantiating and serializing

o = A_1_0(
    del_=BDelimited_1_0(
        var=[CVariable_1_0(a=[1, 2], b=0), CVariable_1_0(a=[3], b=4)],
        fix=[CFixed_1_0(a=[5, 6])],
    ),
)
01 17 00 00 00 02 04 00 00 00 02 01 02 00 03 00 00 00 01 03 04 01 02 00 00 00 05 06
|  |_________/ |  |_________/ |  |___/ |  |_________/ |  |  |  |  |_________/ |___/
|  |           |  |           |  |     |  |           |  |  |  |  |           |
|  |           |  |           |  |     |  |           |  |  |  |  |           Array a (fixed length)
|  |           |  |           |  |     |  |           |  |  |  |  Delimiter header of the only array element
|  |           |  |           |  |     |  |           |  |  |  Array fix contains 1 element
|  |           |  |           |  |     |  |           |  |  Field b
|  |           |  |           |  |     |  |           |  Array a
|  |           |  |           |  |     |  |           Array a contains 1 element
|  |           |  |           |  |     |  Delimiter header of the 2nd array element
|  |           |  |           |  |     Field b left uninitialized
|  |           |  |           |  Array a
|  |           |  |           Array a contains 2 elements
|  |           |  Delimiter header of the 1st array element
|  |           Array var contains 2 elements
|  Delimiter header of BDelimited.1.0 del
Union tag of del

Deserializing A.1.1

Now, the serialized representation obtained above can be deserialized using data types of different versions that contain different fields. The result is well-defined thanks to the data type extensibility capabilities of UAVCAN v1.

DSDL definitions

# A.1.1
@union
BSealed.1.0    sea
BDelimited.1.1 del
@extent 56 * 8
# BDelimited.1.1.uavcan
CVariable.1.1[<=2] var
CFixed.1.1[<=2]    fix
@extent 40 * 8
# CVariable.1.1.uavcan
uint8[<=2] a
@extent 4 * 8
# CFixed.1.1.uavcan
uint8[3] a
int8 b
@extent 4 * 8

Deserializing

o = pyuavcan.dsdl.deserialize(A_1_1, [memoryview(sr)])
assert o.sea is None
assert o.del_ is not None
assert len(o.del_.var) == 2
assert len(o.del_.fix) == 1
assert list(o.del_.var[0].a) == [1, 2]
assert list(o.del_.var[1].a) == [3]        # b is implicitly truncated
assert list(o.del_.fix[0].a) == [5, 6, 0]  # 3rd is implicitly zero-extended
assert o.del_.fix[0].b == 0                # b is implicitly zero-extended

Cross-linking the background here for future reference: