Tutorial 22
Complex length fields.
Up until v5.0 of the CommsDSL Specification the
semanticType="length" property was allowed to be assinged only for <int> fields. Since v5.0
it is allowed for complex fields, such as <bundle> or <bitfield>. However,
the custom code is required to be injected which implements the functionality of
setting and retrieving numeric length values.
This tutorial demonstrates using the length field, which is serialized as one byte in case the
remaining length value is 254 or lower. Otherwise is is serialized as 3 bytes, where the
first one is special value 0xff (255), followed by the 2 bytes of real length.
The schema file defines the Length field as the following <bundle>:
<bundle name="Length" semanticType="length" valueOverride="replace"> <int name="Short" type="uint8"> <special name="LongForm" val="0xff" /> </int> <optional name="Long" cond="$Short = 0xff" defaultMode="missing"> <int name="ActLong" type="uint16" /> </optional> </bundle>
Usage of valueOverride property ensures that the custom code of value retrieval is injected into the code generation.
The custom code itself (residing in dsl_src/include/tutorial22/field/Length.h.value and finding its way to the actual code in include/tutorial22/field/Length.h) defines three functions:
/// @brief Get length value std::size_t getValue() const { if (!field_short().isLongForm()) { return static_cast<std::size_t>(field_short().value()); } COMMS_ASSERT(field_long().doesExist()); // Make sure the field in the consistent state return static_cast<std::size_t>(field_long().field().value()); } /// @brief Set length value void setValue(std::size_t val) { if (val < Field_short::valueLongForm()) { field_short().setValue(val); field_long().setMissing(); return; } field_short().setLongForm(); field_long().field().setValue(val); field_long().setExists(); } /// @brief Maximal possible length value static constexpr std::size_t maxValue() { return std::numeric_limits<typename Field_long::Field::ValueType>::max(); }
NOTE, that so far (in all the previous tutorials) the field's value has been accessed
by reference using value() member functions. Version v5.0 of the
COMMS Library introduces extra getValue() and
setValue() functions for every field class, which are just wrappers around the value() one.
They can be overridden when custom functionality of
dealing with field's value is required, like in the case described in this tutorial.
Also when dealing with remaining length value, some internal functionality of the
COMMS Library requires compile time knowledge
of maximal possible length value. As the result additional maxValue() function
also is required to be provided. It needs to be constexpr to provide the information
at compile time.
The test of this tutorial implements list of TLV properties described in the tutorial4. The code in the ClientSession that prepares the message to be sent out looks like this:
void ClientSession::sendMsg1() { Msg1 msg; auto& listOfProps = msg.field_f1().value(); // vector of variant fields listOfProps.resize(2); assert(msg.doLength() == 0U); assert(!listOfProps[0].valid()); assert(!listOfProps[1].valid()); listOfProps[0].initField_prop1().field_val().value() = 0x12; listOfProps[1].initField_prop2().field_val().value().assign(300, 'a'); // Force long length form. msg.doRefresh(); // Bring message to a consistent state sendMessage(msg); }
Please analyze the raw data dump produced by both the "client" and the "server" application
of this tutorial to see that in case of first property the short form of the Length field
is used, while for the second one the long form is in place.
Summary
- Version v5.0 of CommsDSL Specification
allows using complex fields like
<bundle>or<bitfield>to be used as length withsemanticType="length"property assigned. - Version v5.0 of the COMMS Library uses
extra
getValue()andsetValue()wrapping functions (in addition to thevalue()), which can be overridden in the injected code to provide custom value handling functionality. - In most cases custom length retrieval functionality also requires providing
maxValue()static constexpr function, which provides maximal remaining length value.
Read Previous Tutorial <-----------------------> Read Next Tutorial