27#include <QtCore/QString>
29#include "comms/comms.h"
30#include "cc_tools_qt/Api.h"
32COMMS_MSVC_WARNING_PUSH
33COMMS_MSVC_WARNING_DISABLE(4127)
38namespace field_wrapper
41class FieldWrapperHandler;
47 typedef std::vector<std::uint8_t> SerialisedSeq;
49 typedef std::unique_ptr<FieldWrapper> BasePtr;
54 std::size_t length()
const;
60 SerialisedSeq getSerialisedValue()
const;
62 bool setSerialisedValue(
const SerialisedSeq& value);
64 QString getSerialisedString()
const;
66 bool setSerialisedString(
const QString& str);
68 void dispatch(FieldWrapperHandler& handler);
72 bool canWrite()
const;
77 virtual std::size_t lengthImpl()
const = 0;
78 virtual bool validImpl()
const = 0;
79 virtual SerialisedSeq getSerialisedValueImpl()
const = 0;
80 virtual bool setSerialisedValueImpl(
const SerialisedSeq& value) = 0;
81 virtual void dispatchImpl(FieldWrapperHandler& handler) = 0;
82 virtual BasePtr upCloneImpl() = 0;
83 virtual bool canWriteImpl()
const = 0;
84 virtual void resetImpl() = 0;
87template <
typename TBase,
typename TField>
88class FieldWrapperT :
public TBase
92 struct HasPrefixSuffixTag {};
93 struct NoPrefixSuffixTag {};
96 typedef typename Base::SerialisedSeq SerialisedSeq;
97 typedef typename Base::BasePtr BasePtr;
99 virtual ~FieldWrapperT() noexcept = default;
103 using Field = TField;
105 explicit FieldWrapperT(Field& fieldRef)
110 virtual std::size_t lengthImpl()
const override
112 return m_field.length();
115 virtual bool validImpl()
const override
117 return m_field.valid();
125 const Field& field()
const
130 virtual SerialisedSeq getSerialisedValueImpl()
const override
133 seq.reserve(m_field.length());
134 auto iter = std::back_inserter(seq);
135 [[maybe_unused]]
auto es = m_field.write(iter, seq.max_size());
136 assert(es == comms::ErrorStatus::Success);
137 assert(seq.size() == m_field.length());
141 virtual bool setSerialisedValueImpl(
const SerialisedSeq& value)
override
147 if ((!CollectionPrefixDetect<Field, IsCollection>::HasSizeFieldPrefix) &&
148 (!CollectionPrefixDetect<Field, IsCollection>::HasSerLengthFieldPrefix) &&
149 (!CollectionPrefixDetect<Field, IsCollection>::HasTrailingFieldSuffix) &&
150 (!CollectionPrefixDetect<Field, IsCollection>::HasTerminationFieldSuffix)) {
151 auto iter = &value[0];
152 auto es = m_field.read(iter, value.size());
153 return es == comms::ErrorStatus::Success;
156 SerialisedSeq newVal;
157 if (!writeSerialisedSize(newVal, value.size(), SerialisedSizePrefixTag())) {
161 if (!writeSerialisedLength(newVal, value.size(), SerialisedLengthPrefixTag())) {
165 auto writeIter = std::back_inserter(newVal);
166 std::copy(value.begin(), value.end(), writeIter);
168 if (!writeTrailSuffix(newVal, SerialisedTrailSuffixTag())) {
172 if (!writeTermSuffix(newVal, SerialisedTermSuffixTag())) {
176 auto iter = &newVal[0];
177 auto es = m_field.read(iter, newVal.size());
178 return es == comms::ErrorStatus::Success;
181 virtual BasePtr upCloneImpl()
override
183 return static_cast<Base*
>(
this)->clone();
186 virtual bool canWriteImpl()
const override
188 return m_field.canWrite();
191 virtual void resetImpl()
override
197 template <
typename T,
bool TIsCollection>
198 struct CollectionPrefixDetect
200 static const bool HasSizeFieldPrefix =
false;
201 static const bool HasSerLengthFieldPrefix =
false;
202 static const bool HasTrailingFieldSuffix =
false;
203 static const bool HasTerminationFieldSuffix =
false;
206 template <
typename T>
207 struct CollectionPrefixDetect<T, true>
209 static const bool HasSizeFieldPrefix = Field::hasSizeFieldPrefix();
210 static const bool HasSerLengthFieldPrefix = Field::hasSerLengthFieldPrefix();
211 static const bool HasTrailingFieldSuffix = TField::hasTrailingFieldSuffix();
212 static const bool HasTerminationFieldSuffix = Field::hasTerminationFieldSuffix();
215 static constexpr bool IsCollection = comms::field::isString<Field>() || comms::field::isArrayList<Field>();
217 typedef typename std::conditional<
218 CollectionPrefixDetect<Field, IsCollection>::HasSizeFieldPrefix,
221 >::type SerialisedSizePrefixTag;
223 typedef typename std::conditional<
224 CollectionPrefixDetect<Field, IsCollection>::HasSerLengthFieldPrefix,
227 >::type SerialisedLengthPrefixTag;
229 typedef typename std::conditional<
230 CollectionPrefixDetect<Field, IsCollection>::HasTrailingFieldSuffix,
233 >::type SerialisedTrailSuffixTag;
235 typedef typename std::conditional<
236 CollectionPrefixDetect<Field, IsCollection>::HasTerminationFieldSuffix,
239 >::type SerialisedTermSuffixTag;
241 bool writeSerialisedSize(SerialisedSeq& seq, std::size_t sizeVal, HasPrefixSuffixTag)
243 typedef typename Field::SizeFieldPrefix SizePrefixField;
245 SizePrefixField sizePrefixField;
246 sizePrefixField.setValue(sizeVal);
247 auto writeIter = std::back_inserter(seq);
248 auto es = sizePrefixField.write(writeIter, seq.max_size() - seq.size());
249 return es == comms::ErrorStatus::Success;
252 bool writeSerialisedSize([[maybe_unused]] SerialisedSeq& seq, [[maybe_unused]] std::size_t sizeVal, NoPrefixSuffixTag)
257 bool writeSerialisedLength(SerialisedSeq& seq, std::size_t sizeVal, HasPrefixSuffixTag)
259 typedef typename Field::SerLengthFieldPrefix LengthPrefixField;
261 LengthPrefixField lengthPrefixField;
262 lengthPrefixField.setValue(sizeVal);
263 auto writeIter = std::back_inserter(seq);
264 auto es = lengthPrefixField.write(writeIter, seq.max_size() - seq.size());
265 return es == comms::ErrorStatus::Success;
268 bool writeSerialisedLength([[maybe_unused]] SerialisedSeq& seq, [[maybe_unused]] std::size_t sizeVal, NoPrefixSuffixTag)
273 bool writeTrailSuffix(SerialisedSeq& seq, HasPrefixSuffixTag)
275 typedef typename Field::TrailingFieldSuffix TrailingSuffixField;
276 TrailingSuffixField trailingSuffixField;
277 auto writeIter = std::back_inserter(seq);
278 auto es = trailingSuffixField.write(writeIter, seq.max_size() - seq.size());
279 return es == comms::ErrorStatus::Success;
282 bool writeTrailSuffix([[maybe_unused]] SerialisedSeq& seq, NoPrefixSuffixTag)
287 bool writeTermSuffix(SerialisedSeq& seq, HasPrefixSuffixTag)
289 typedef typename Field::TerminationFieldSuffix TermSuffixField;
290 TermSuffixField termSuffixField;
291 auto writeIter = std::back_inserter(seq);
292 auto es = termSuffixField.write(writeIter, seq.max_size() - seq.size());
293 return es == comms::ErrorStatus::Success;
296 bool writeTermSuffix([[maybe_unused]] SerialisedSeq& seq, NoPrefixSuffixTag)
305typedef FieldWrapper::BasePtr FieldWrapperPtr;
311COMMS_MSVC_WARNING_POP