22#include "cc_tools_qt/ToolsExtraInfoMessage.h"
23#include "cc_tools_qt/ToolsInvalidMessage.h"
24#include "cc_tools_qt/ToolsRawDataMessage.h"
25#include "cc_tools_qt/property/message.h"
27#include <QtCore/QJsonObject>
28#include <QtCore/QJsonDocument>
29#include <QtCore/QByteArray>
39template <
typename TMsgBase,
class TProtFrame,
typename TMsgFactory,
typename TTransportMsg>
40class ToolsFrameBase :
public ToolsFrame
42 using Base = ToolsFrame;
44 using ProtInterface =
typename TMsgBase::ProtInterface;
45 using DataSeq =
typename Base::DataSeq;
47 using TransportMsg = TTransportMsg;
50 using InvalidMsg = ToolsInvalidMessage<TMsgBase>;
52 using RawDataMsg = ToolsRawDataMessage<TMsgBase>;
55 using ExtraInfoMsg = ToolsExtraInfoMessage<TMsgBase>;
57 using ProtFrame = TProtFrame;
59 ToolsFrameBase() =
default;
62 virtual ToolsMessagesList readDataImpl(
const ToolsDataInfo& dataInfo,
bool final)
override
64 m_inData.reserve(m_inData.size() + dataInfo.m_data.size());
65 m_inData.insert(m_inData.end(), dataInfo.m_data.begin(), dataInfo.m_data.end());
67 ToolsMessagesList allMsgs;
68 std::size_t consumed = 0U;
70 auto checkGarbageFunc =
73 if (m_garbage.empty()) {
78 updateRawDataInternal(m_garbage, *invalidMsgPtr);
79 allMsgs.push_back(std::move(invalidMsgPtr));
83 using ProtMsgPtr =
typename ProtFrame::MsgPtr;
84 using ReadIter =
typename ProtInterface::ReadIterator;
85 while (consumed < m_inData.size()) {
88 ReadIter readIterBeg = m_inData.data() + consumed;
89 ReadIter readIter = readIterBeg;
90 auto remLen = m_inData.size() - consumed;
100 comms::frame::msgId(msgId),
101 comms::frame::msgIndex(idx));
103 if (es == comms::ErrorStatus::NotEnoughData) {
107 if (es == comms::ErrorStatus::MsgAllocFailure) {
108 [[maybe_unused]]
static constexpr bool Must_not_be_happen =
false;
109 assert(Must_not_be_happen);
113 if (es != comms::ErrorStatus::Success) {
114 m_garbage.push_back(*readIterBeg);
115 static constexpr std::size_t GarbageLimit = 512;
116 if (GarbageLimit <= m_garbage.size()) {
126 auto diff =
static_cast<std::size_t
>(std::distance(readIterBeg, readIter));
129 auto toolsMsg = m_factory.createMessage(msgId,
static_cast<unsigned>(idx));
131 [[maybe_unused]]
static constexpr bool Protocol_and_Tools_Frames_Out_of_Sync =
false;
132 assert(Protocol_and_Tools_Frames_Out_of_Sync);
134 m_garbage.reserve(m_garbage.size() + diff);
135 m_garbage.insert(m_garbage.end(), readIterBeg, readIter);
140 toolsMsg->assignProtMessage(msgPtr.get());
142 DataSeq data(readIterBeg, readIter);
143 updateTransportInternal(data, *toolsMsg);
144 updateRawDataInternal(data, *toolsMsg);
145 allMsgs.push_back(std::move(toolsMsg));
148 static_cast<void>(
final);
150 assert(consumed <= m_inData.size());
151 using DiffType =
typename std::iterator_traits<DataSeq::iterator>::difference_type;
152 m_inData.erase(m_inData.begin(), m_inData.begin() +
static_cast<DiffType
>(consumed));
154 if (
final && (!m_inData.empty())) {
155 m_garbage.reserve(m_garbage.size() + m_inData.size());
156 m_garbage.insert(m_garbage.end(), m_inData.begin(), m_inData.end());
161 if (!dataInfo.m_extraProperties.isEmpty()) {
162 auto jsonObj = QJsonObject::fromVariantMap(dataInfo.m_extraProperties);
163 QJsonDocument doc(jsonObj);
164 auto jsonData = doc.toJson();
165 DataSeq jsonRawBytes(jsonData.begin(), jsonData.end());
167 for (
auto& m : allMsgs) {
168 property::message::ToolsMsgExtraInfo().setTo(dataInfo.m_extraProperties, *m);
169 updateExtraInfoInternal(jsonRawBytes, *m);
176 virtual void updateMessageImpl(ToolsMessage& msg)
override
178 auto data = msg.encodeFramed(*
this);
179 updateTransportInternal(data, msg);
180 updateRawDataInternal(data, msg);
182 auto extraProps = property::message::ToolsMsgExtraInfo().getFrom(msg);
183 bool extraInfoMsgIsForced = property::message::ToolsMsgForceExtraInfoExistence().getFrom(msg);
184 if (extraProps.isEmpty() && (!extraInfoMsgIsForced)) {
185 property::message::ToolsMsgExtraInfoMsg().setTo(
ToolsMessagePtr(), msg);
189 auto extraInfoMsgPtr = std::make_unique<ExtraInfoMsg>();
190 if (extraProps.isEmpty()) {
191 property::message::ToolsMsgExtraInfoMsg().setTo(
ToolsMessagePtr(extraInfoMsgPtr.release()), msg);
195 auto jsonObj = QJsonObject::fromVariantMap(extraProps);
196 QJsonDocument doc(jsonObj);
197 auto jsonData = doc.toJson();
198 DataSeq jsonRawBytes(jsonData.begin(), jsonData.end());
199 updateExtraInfoInternal(jsonRawBytes, msg);
217 virtual ToolsMessagesList createAllMessagesImpl()
override
219 return m_factory.createAllMessages();
222 virtual ToolsMessagePtr createMessageImpl(
const QString& idAsString,
unsigned idx)
override
224 return m_factory.createMessage(idAsString, idx);
227 virtual DataSeq writeProtMsgImpl(
const void* protInterface)
override
229 assert(protInterface !=
nullptr);
230 auto& msg = *(
reinterpret_cast<const ProtInterface*
>(protInterface));
232 data.reserve(m_frame.length(msg));
234 auto writeIter = std::back_inserter(data);
235 auto es = m_frame.write(msg, writeIter, data.max_size());
236 if (es == comms::ErrorStatus::UpdateRequired) {
237 auto updateIter = data.data();
238 es = m_frame.update(msg, updateIter, data.size());
241 if (es != comms::ErrorStatus::Success) {
242 [[maybe_unused]]
static constexpr bool Unexpected_write_update_failure =
false;
243 assert(Unexpected_write_update_failure);
251 void updateTransportInternal(
const DataSeq& data, ToolsMessage& msg)
254 if (!transportMsg->decodeData(data)) {
255 std::cerr <<
"ERROR: Failed to decode transport message: " << std::hex;
256 std::copy(data.begin(), data.end(), std::ostream_iterator<unsigned>(std::cerr,
" "));
257 std::cerr << std::dec << std::endl;
259 [[maybe_unused]]
static constexpr bool Must_not_be_happen =
false;
260 assert(Must_not_be_happen);
263 property::message::ToolsMsgTransportMsg().setTo(std::move(transportMsg), msg);
266 void updateRawDataInternal(
const DataSeq& data, ToolsMessage& msg)
269 if (!rawDataMsg->decodeData(data)) {
270 std::cerr <<
"ERROR: Failed to decode raw data message: " << std::hex;
271 std::copy(data.begin(), data.end(), std::ostream_iterator<unsigned>(std::cerr,
" "));
272 std::cerr << std::dec << std::endl;
274 [[maybe_unused]]
static constexpr bool Must_not_be_happen =
false;
275 assert(Must_not_be_happen);
278 property::message::ToolsMsgRawDataMsg().setTo(std::move(rawDataMsg), msg);
281 void updateExtraInfoInternal(
const DataSeq& jsonRawBytes, ToolsMessage& msg)
284 if (!extraInfoMsg->decodeData(jsonRawBytes)) {
285 std::cerr <<
"ERROR: Failed to decode extra info:\n";
286 std::copy(jsonRawBytes.begin(), jsonRawBytes.end(), std::ostream_iterator<char>(std::cerr,
" "));
287 std::cerr << std::endl;
289 [[maybe_unused]]
static constexpr bool Must_not_be_happen =
false;
290 assert(Must_not_be_happen);
293 property::message::ToolsMsgExtraInfoMsg().setTo(std::move(extraInfoMsg), msg);
297 TMsgFactory m_factory;