20#include "comms/comms.h"
22#include <QtCore/QString>
30COMMS_MSVC_WARNING_PUSH
31COMMS_MSVC_WARNING_DISABLE(4127)
39template <
typename TBase,
typename TField>
40class ToolsFieldBase :
public TBase
45 using SerialisedSeq =
typename Base::SerialisedSeq;
46 using Ptr =
typename Base::Ptr;
50 virtual ~ToolsFieldBase() noexcept = default;
54 explicit ToolsFieldBase(Field& fieldRef)
59 virtual const char* nameImpl()
const override
61 static_assert(Field::hasName(),
"The field class is expected use comms::option::def::HasName and define name() function.");
62 return m_field.name();
65 virtual std::size_t lengthImpl()
const override
67 return m_field.length();
70 virtual bool validImpl()
const override
72 return m_field.valid();
75 virtual bool isReadOnlyImpl()
const override
77 return Field::hasFixedValue();
80 virtual bool isHiddenSerializationImpl()
const override
82 return Field::hasEmptySerialization();
90 const Field& field()
const
95 virtual SerialisedSeq getSerialisedValueImpl()
const override
98 seq.reserve(m_field.length());
99 auto iter = std::back_inserter(seq);
100 [[maybe_unused]]
auto es = m_field.write(iter, seq.max_size());
101 assert(es == comms::ErrorStatus::Success);
102 assert(seq.size() == m_field.length());
106 virtual bool setSerialisedValueImpl(
const SerialisedSeq& value)
override
112 if ((!CollectionPrefixDetect<Field, IsCollection>::HasSizeFieldPrefix) &&
113 (!CollectionPrefixDetect<Field, IsCollection>::HasSerLengthFieldPrefix) &&
114 (!CollectionPrefixDetect<Field, IsCollection>::HasTrailingFieldSuffix) &&
115 (!CollectionPrefixDetect<Field, IsCollection>::HasTerminationFieldSuffix)) {
116 auto iter = &value[0];
117 auto es = m_field.read(iter, value.size());
118 return es == comms::ErrorStatus::Success;
121 SerialisedSeq newVal;
122 if (!writeSerialisedSize(newVal, value.size(), SerialisedSizePrefixTag())) {
126 if (!writeSerialisedLength(newVal, value.size(), SerialisedLengthPrefixTag())) {
130 auto writeIter = std::back_inserter(newVal);
131 std::copy(value.begin(), value.end(), writeIter);
133 if (!writeTrailSuffix(newVal, SerialisedTrailSuffixTag())) {
137 if (!writeTermSuffix(newVal, SerialisedTermSuffixTag())) {
141 auto iter = &newVal[0];
142 auto es = m_field.read(iter, newVal.size());
143 return es == comms::ErrorStatus::Success;
146 virtual bool canWriteImpl()
const override
148 return m_field.canWrite();
151 virtual void resetImpl()
override
157 struct HasPrefixSuffixTag {};
158 struct NoPrefixSuffixTag {};
160 template <
typename T,
bool TIsCollection>
161 struct CollectionPrefixDetect
163 static const bool HasSizeFieldPrefix =
false;
164 static const bool HasSerLengthFieldPrefix =
false;
165 static const bool HasTrailingFieldSuffix =
false;
166 static const bool HasTerminationFieldSuffix =
false;
169 template <
typename T>
170 struct CollectionPrefixDetect<T, true>
172 static const bool HasSizeFieldPrefix = Field::hasSizeFieldPrefix();
173 static const bool HasSerLengthFieldPrefix = Field::hasSerLengthFieldPrefix();
174 static const bool HasTrailingFieldSuffix = TField::hasTrailingFieldSuffix();
175 static const bool HasTerminationFieldSuffix = Field::hasTerminationFieldSuffix();
178 static constexpr bool IsCollection = comms::field::isString<Field>() || comms::field::isArrayList<Field>();
180 using SerialisedSizePrefixTag =
182 CollectionPrefixDetect<Field, IsCollection>::HasSizeFieldPrefix,
187 using SerialisedLengthPrefixTag =
189 CollectionPrefixDetect<Field, IsCollection>::HasSerLengthFieldPrefix,
194 using SerialisedTrailSuffixTag =
196 CollectionPrefixDetect<Field, IsCollection>::HasTrailingFieldSuffix,
201 using SerialisedTermSuffixTag =
203 CollectionPrefixDetect<Field, IsCollection>::HasTerminationFieldSuffix,
208 bool writeSerialisedSize(SerialisedSeq& seq, std::size_t sizeVal, HasPrefixSuffixTag)
210 using SizePrefixField =
typename Field::SizeFieldPrefix;
212 SizePrefixField sizePrefixField;
213 sizePrefixField.setValue(sizeVal);
214 auto writeIter = std::back_inserter(seq);
215 auto es = sizePrefixField.write(writeIter, seq.max_size() - seq.size());
216 return es == comms::ErrorStatus::Success;
219 bool writeSerialisedSize([[maybe_unused]] SerialisedSeq& seq, [[maybe_unused]] std::size_t sizeVal, NoPrefixSuffixTag)
224 bool writeSerialisedLength(SerialisedSeq& seq, std::size_t sizeVal, HasPrefixSuffixTag)
226 using LengthPrefixField =
typename Field::SerLengthFieldPrefix;
228 LengthPrefixField lengthPrefixField;
229 lengthPrefixField.setValue(sizeVal);
230 auto writeIter = std::back_inserter(seq);
231 auto es = lengthPrefixField.write(writeIter, seq.max_size() - seq.size());
232 return es == comms::ErrorStatus::Success;
235 bool writeSerialisedLength([[maybe_unused]] SerialisedSeq& seq, [[maybe_unused]] std::size_t sizeVal, NoPrefixSuffixTag)
240 bool writeTrailSuffix(SerialisedSeq& seq, HasPrefixSuffixTag)
242 using TrailingSuffixField =
typename Field::TrailingFieldSuffix;
244 TrailingSuffixField trailingSuffixField;
245 auto writeIter = std::back_inserter(seq);
246 auto es = trailingSuffixField.write(writeIter, seq.max_size() - seq.size());
247 return es == comms::ErrorStatus::Success;
250 bool writeTrailSuffix([[maybe_unused]] SerialisedSeq& seq, NoPrefixSuffixTag)
255 bool writeTermSuffix(SerialisedSeq& seq, HasPrefixSuffixTag)
257 using TermSuffixField =
typename Field::TerminationFieldSuffix;
258 TermSuffixField termSuffixField;
259 auto writeIter = std::back_inserter(seq);
260 auto es = termSuffixField.write(writeIter, seq.max_size() - seq.size());
261 return es == comms::ErrorStatus::Success;
264 bool writeTermSuffix([[maybe_unused]] SerialisedSeq& seq, NoPrefixSuffixTag)
276COMMS_MSVC_WARNING_POP