The <bundle> is a container field, which aggregates multiple independent fields (of any kind) into a single one. The <bundle> field has all the common properties.
Member fields need to be listed as children XML elements of the <bundle>.
<?xml version="1.0" encoding="UTF-8"?>
<schema name="MyProtocol" endian="big">
<fields>
<bundle name="SomeBundle">
<int name="SomeIntMember" type="uint8" />
<set name="SomeSetMember" length="1">
...
</set>
<enum name="SomeEnumMember" type="uint8">
...
</enum>
<bundle name="SomeInnerBundle">
...
</bundle>
</bundle>
</fields>
</schema>
If there is any other property defined as XML child of the <bundle>, then all the members must be wrapped in <members> XML element for separation.
<?xml version="1.0" encoding="UTF-8"?>
<schema name="MyProtocol" endian="big">
<fields>
<bundle name="SomeBundle">
<displayName value="Proper Bundle Name" />
<members>
<int name="SomeIntMember" type="uint8" bitLength="3" />
<set name="SomeSetMember" length="1">
...
</set>
<enum name="SomeEnumMember" type="uint8">
...
</enum>
<bundle name="SomeInnerBundle">
...
</bundle>
</members>
</bundle>
</fields>
</schema>
Like any other field, <bundle> supports reuse of any other <bundle>. Such reuse copies all the fields from original <bundle> in addition to all the properties. Any new defined member field gets appended to the copied ones.
<?xml version="1.0" encoding="UTF-8"?>
<schema name="MyProtocol" endian="big">
<fields>
<bundle name="SomeBundle">
<int name="F1" type="uint32" />
<float name="F2" type="float" />
</bundle>
<bundle name="SomeOtherBundle" reuse="SomeBundle">
<string name="F3" length="16" />
</bundle>
</fields>
</schema>
In the example above SomeOtherBundle has 3 member fields: F1, F2, and F3.
It is possible to replace some of the copied member fields after reuse using <replace> child node, which wraps the replacing fields.
<?xml version="1.0" encoding="UTF-8"?>
<schema name="MyProtocol" endian="big">
<fields>
<bundle name="SomeBundle">
<int name="Mem1" type="uint8" />
<enum name="Mem2" type="uint8">
<validValue name="V0" val="0" />
<validValue name="V1" val="1" />
</enum>
</bundle>
<bundle name="SomeOtherBundle" reuse="SomeBundle">
<replace>
<set name="Mem2" type="uint8">
<bit name="B0" idx="0" />
<bit name="B1" idx="1" />
</set>
</replace>
</bundle>
</fields>
</schema>
The replacing field must have the same name as the reused member field it is replacing. The <replace> child node may have multiple member fields replacing the copied ones. The order of the fields inside the <replace> child node is not important, the order of the fields is determined by the original <bundle> field, which was reused.
It is possible to combine <replace>-ing copied member fields and extending the <bundle> with new fields.
<?xml version="1.0" encoding="UTF-8"?>
<schema name="MyProtocol" endian="big">
<fields>
<bundle name="SomeBundle">
<int name="Mem1" type="uint8" />
<enum name="Mem2" type="uint8">
<validValue name="V0" val="0" />
<validValue name="V1" val="1" />
</enum>
</bundle>
<bundle name="SomeOtherBundle" reuse="SomeBundle">
<replace>
<set name="Mem2" type="uint8">
<bit name="B0" idx="0" />
<bit name="B1" idx="1" />
</set>
</replace>
<members>
<int name="Mem3" type="uint16" />
</members>
</bundle>
</fields>
</schema>
The example above is equivalent to defining SomeOtherBundle
<bundle> field
in the following way.
<?xml version="1.0" encoding="UTF-8"?>
<schema name="MyProtocol" endian="big">
<fields>
<bundle name="SomeOtherBundle">
<int name="Mem1" type="uint8" />
<set name="Mem2" type="uint8">
<bit name="B0" idx="0" />
<bit name="B1" idx="1" />
</set>
<int name="Mem3" type="uint16" />
</bundle>
</fields>
</schema>
Sometimes an existing member field may be renamed and/or moved. It is possible to create alias names for the fields to keep the old client code being able to compile and work. Please refer to Aliases chapter for more details.
The valid operation of every <bundle> means invoking the valid operation for every one of its member fields. However, the valid values of fields may be interdependent. There may be a need to introduce extra validity checks on the <bundle> contents. To do so the validCond property referencing appropriate member fields of the <bundle> itself can be used. The syntax is the same as with the <optional> field’s existence conditions (described later).
<?xml version="1.0" encoding="UTF-8"?>
<schema ...>
<fields>
<bundle name="SomeBundle" validCond="$Mem1 != $Mem2">
<int name="Mem1" type="uint8" />
<int name="Mem2" type="uint16" />
</bundle>
</fields>
</schema>
In case of multiple conditions the validCond needs to be specified
as the <validCond>
child node with a single <and>
or <or>
immediate child.
Nested <and>
and/or <or>
conditions are allowed in the same way as with the
<optional> field’s existence conditions.
The only difference is that the inner child nodes must be named validCond
instead of cond
.
<?xml version="1.0" encoding="UTF-8"?>
<schema ...>
<fields>
<bundle name="SomeBundle">
<members>
<int name="Mem1" type="uint8" />
<int name="Mem2" type="uint16" />
</members>
<validCond>
<or>
<validCond value="$Mem1 = 0" />
<validCond value="$Mem2 != 0" />
</or>
</validCond>
</bundle>
</fields>
</schema>
In case some other <bundle> have similar fields and the same extra validity conditions apply to the <bundle> field being defined, it is possible to copy the conditions using copyValidCondFrom property.
<?xml version="1.0" encoding="UTF-8"?>
<schema ...>
<fields>
<bundle name="SomeBundle" validCond="$Mem1 != $Mem2">
<int name="Mem1" type="uint8" />
<int name="Mem2" type="uint16" />
</bundle>
<bundle name="SomeOtherBundle" copyValidCondFrom="SomeBundle">
<int name="Mem3" type="uint32" />
<int name="Mem1" type="uint8" />
<int name="Mem2" type="uint16" />
</bundle>
</fields>
</schema>
Note that copyValidCondFrom is an action property, which causes the copy
of the original validity conditions. When such field is reused
in the future the original definition doesn’t really have property named copyValidCondFrom to be
copied, only the real validity condition(s). The SomeOtherBundle
definition above is equivalent to:
<?xml version="1.0" encoding="UTF-8"?>
<schema ...>
<fields>
<bundle name="SomeOtherBundle" validCond="$Mem1 != $Mem2">
<int name="Mem3" type="uint32" />
<int name="Mem1" type="uint8" />
<int name="Mem2" type="uint16" />
</bundle>
</fields>
</schema>
Use properties table for future references.