{%- if msg_proto_utils_header | length -%} #include "{{ msg_proto_utils_header }}" {%- endif %} #include #include {%- if cpp_namespace is defined and cpp_namespace is not none %} namespace {{ cpp_namespace }} { {%- endif %} // Populate the protobuf Header (field 1) shared by every typed message. static void updateHeader(messages::Header *header, const QDateTime ×tamp, qint16 sequence, quint16 msgId) { if (header) { const auto msecs = timestamp.toMSecsSinceEpoch(); auto proto_timestamp = header->mutable_timestamp(); if (proto_timestamp) { proto_timestamp->set_seconds(msecs / 1000); proto_timestamp->set_nanos((msecs % 1000) * 1000000); } header->set_sequence(sequence); header->set_msgid(msgId); } } {%- for (msg_id_value, msg) in msg_cpp.data.items() %} {%- set has_union = msg['payload'] | selectattr('type', 'equalto', 'union') | list | length > 0 %} // {{ msg['msg_id'] }} ({{ msg['msg_id_hex_string'] }}) // payload: {{ msg_cpp.field_list(msg_id_value) | join(", ") }} // serializeProto: msg struct -> QByteArray of serialized protobuf data (header populated from params) bool serializeProto([[maybe_unused]] const {{ msg['msg_name'] }}Payload &src, const QDateTime ×tamp, qint16 sequence, quint16 msgId, QByteArray &dst) { {%- if has_union %} qDebug().noquote() << "WARNING: MsgId={{ msg['msg_name'] }} contains union/oneof field(s); protobuf serialization is partial"; {%- endif %} messages::{{ msg['msg_name'] }} proto; updateHeader(proto.mutable_header(), timestamp, sequence, msgId); {%- for field in msg['payload'] %} {%- if field['type'] != "union" %} // {{ field['type'] ~ "-" ~ field['name'] }} proto.set_{{ field['name'].lower() }}(src.{{ field['name'] }}.value); {%- else %} // TODO: {{ field['type'] ~ "-" ~ field['name'] }} {%- endif %} {%- endfor %} std::string out; if (proto.SerializeToString(&out)) { dst = QByteArray::fromStdString(out); return true; } else { dst = QByteArray(); return false; } } // {{ msg['msg_id'] }} ({{ msg['msg_id_hex_string'] }}) // payload: {{ msg_cpp.field_list(msg_id_value) | join(", ") }} // deserializeProto: QByteArray of serialized protobuf data -> msg struct (false on parse failure) bool deserializeProto(const QByteArray &bytes, [[maybe_unused]] {{ msg['msg_name'] }}Payload &dst) { {%- if has_union %} qDebug().noquote() << "WARNING: MsgId={{ msg['msg_name'] }} contains union/oneof field(s); protobuf deserialization is partial"; {%- endif %} messages::{{ msg['msg_name'] }} proto; if (proto.ParseFromArray(bytes.constData(), bytes.size())) { {%- for field in msg['payload'] %} {%- if field['type'] != "union" %} // {{ field['type'] ~ "-" ~ field['name'] }} dst.{{ field['name'] }}.value = proto.{{ field['name'].lower() }}(); {%- else %} // TODO: {{ field['type'] ~ "-" ~ field['name'] }} {%- endif %} {%- endfor %} return true; } else { return false; } } {%- endfor %} bool canMessageToProtobufByteArray(const QDateTime ×tamp, const Can::Message &msg, QByteArray &dst) { switch (msg.msgId) { {%- for (msg_id_value, msg) in msg_cpp.data.items() %} case {{ msg['msg_id'] }}: { {{ msg['msg_name'] }}Payload payload; if (payload.fromQByteArray(msg.data)) { return serializeProto(payload, timestamp, msg.sequence, msg.msgId, dst); } else { dst = QByteArray(); return false; } } {%- endfor %} default: qDebug().noquote() << QString("WARNING: MsgId=0x%1 not handled").arg(msg.msgId, 4, 16, QChar('0')); dst = QByteArray(); return false; break; } } // Maps a msgId to its fully-qualified protobuf message name for descriptor-pool lookup. const std::string &msgIdToProtoName(quint16 msgId) { static const std::unordered_map names = { {%- for (msg_id_value, msg) in msg_cpp.data.items() %} {%- if cpp_namespace is defined and cpp_namespace is not none %} { {{ msg['msg_id'] }}, "{{ cpp_namespace }}.messages.{{ msg['msg_name'] }}" }, {%- else %} { {{ msg['msg_id'] }}, "messages.{{ msg['msg_name'] }}" }, {%- endif %} {%- endfor %} }; static const std::string empty; const auto it = names.find(msgId); return it == names.end() ? empty : it->second; } {%- if cpp_namespace is defined and cpp_namespace is not none %} } // namespace {{ cpp_namespace }} {%- endif %}