14#include "comms/details/tag.h"
16#include "comms/field/basic/CommonFuncs.h"
34template <
typename TLenField, comms::ErrorStatus TStatus,
typename TBase>
37 using BaseImpl = TBase;
38 using LenField = TLenField;
39 static const std::size_t MaxAllowedElemLength =
40 static_cast<std::size_t
>(LenField::maxValue());
42 static_assert(!LenField::isVersionDependent(),
43 "Prefix fields must not be version dependent");
46 using ValueType =
typename BaseImpl::ValueType;
47 using ElementType =
typename BaseImpl::ElementType;
57 : BaseImpl(
std::move(val))
66 std::size_t length()
const
69 typename comms::util::LazyShallowConditional<
70 BaseImpl::minElementLength() == BaseImpl::maxElementLength()
75 return lengthInternal(LenFieldLengthTag<>(), ElemLengthTag());
78 std::size_t elementLength(
const ElementType& elem)
const
80 return elementLengthInternal(elem, LenFieldLengthTag<>());
83 static constexpr std::size_t minLength()
85 return LenField::minLength();
88 static constexpr std::size_t maxLength()
90 return basic::CommonFuncs::maxSupportedLength();
93 static constexpr std::size_t minElementLength()
95 return LenField::minLength() + BaseImpl::minElementLength();
98 static constexpr std::size_t maxElementLength()
100 return LenField::maxLength() + BaseImpl::maxElementLength();
103 template <
typename TIter>
104 ErrorStatus readElement(ElementType& elem, TIter& iter, std::size_t& len)
const
106 auto fromIter = iter;
108 auto es = lenField.read(iter, len);
113 auto diff =
static_cast<std::size_t
>(std::distance(fromIter, iter));
116 if (len < lenField.getValue()) {
120 const auto reqLen =
static_cast<std::size_t
>(lenField.getValue());
121 std::size_t elemLen = reqLen;
122 es = BaseImpl::readElement(elem, iter, elemLen);
132 std::advance(iter, elemLen);
137 template <
typename TIter>
138 void readElementNoStatus(ElementType& elem, TIter& iter)
const =
delete;
140 template <
typename TIter>
143 return basic::CommonFuncs::readSequence(*
this, iter, len);
146 static constexpr bool hasReadNoStatus()
151 template <
typename TIter>
152 void readNoStatus(TIter& iter) =
delete;
154 template <
typename TIter>
155 ErrorStatus readN(std::size_t count, TIter& iter, std::size_t& len)
157 return basic::CommonFuncs::readSequenceN(*
this, count, iter, len);
160 template <
typename TIter>
161 void readNoStatusN(std::size_t count, TIter& iter) =
delete;
163 bool canWriteElement(
const ElementType& elem)
const
165 if (!BaseImpl::canWriteElement(elem)) {
169 auto elemLen = elementLength(elem);
170 if (MaxAllowedElemLength < elemLen) {
175 lenField.setValue(elemLen);
176 return lenField.canWrite();
179 template <
typename TIter>
180 ErrorStatus writeElement(
const ElementType& elem, TIter& iter, std::size_t& len)
const
182 if (!canWriteElement(elem)) {
186 auto elemLength = BaseImpl::elementLength(elem);
188 lenField.setValue(elemLength);
189 auto es = lenField.write(iter, len);
194 len -= lenField.length();
195 return BaseImpl::writeElement(elem, iter, len);
198 template <
typename TIter>
199 static void writeElementNoStatus(
const ElementType& elem, TIter& iter) =
delete;
201 bool canWrite()
const
203 return basic::CommonFuncs::canWriteSequence(*
this);
206 template <
typename TIter>
207 ErrorStatus write(TIter& iter, std::size_t len)
const
209 return basic::CommonFuncs::writeSequence(*
this, iter, len);
212 static constexpr bool hasWriteNoStatus()
217 template <
typename TIter>
218 void writeNoStatus(TIter& iter)
const =
delete;
220 template <
typename TIter>
221 ErrorStatus writeN(std::size_t count, TIter& iter, std::size_t& len)
const
223 return basic::CommonFuncs::writeSequenceN(*
this, count, iter, len);
226 template <
typename TIter>
227 void writeNoStatusN(std::size_t count, TIter& iter)
const =
delete;
231 if (!BaseImpl::valid()) {
235 auto& vec = BaseImpl::getValue();
236 for (
auto& elem : vec) {
237 auto elemLen = BaseImpl::elementLength(elem);
238 if (MaxAllowedElemLength < elemLen) {
247 template <
typename... TParams>
248 using FixedLengthLenFieldTag = comms::details::tag::Tag1<>;
250 template <
typename... TParams>
251 using VarLengthLenFieldTag = comms::details::tag::Tag2<>;
253 template <
typename... TParams>
254 using FixedLengthElemTag = comms::details::tag::Tag3<>;
256 template <
typename... TParams>
257 using VarLengthElemTag = comms::details::tag::Tag4<>;
259 template <
typename...>
260 using LenFieldLengthTag =
261 typename comms::util::LazyShallowConditional<
262 LenField::minLength() == LenField::maxLength()
264 FixedLengthLenFieldTag,
268 template<
typename... TParams>
269 std::size_t lengthInternal(FixedLengthLenFieldTag<TParams...>, FixedLengthElemTag<TParams...>)
const
271 return (LenField::minLength() + BaseImpl::minElementLength()) * BaseImpl::getValue().size();
274 template<
typename... TParams>
275 std::size_t lengthInternal(FixedLengthLenFieldTag<TParams...>, VarLengthElemTag<TParams...>)
const
277 return lengthInternalIterative();
280 template <
typename... TParams>
281 std::size_t lengthInternal(VarLengthLenFieldTag<TParams...>, FixedLengthElemTag<TParams...>)
const
283 auto origElemLen = BaseImpl::minElementLength();
284 auto elemLen = std::min(origElemLen, std::size_t(MaxAllowedElemLength));
286 lenField.setValue(elemLen);
287 return (lenField.length() + origElemLen) * BaseImpl::getValue().size();
290 template <
typename... TParams>
291 std::size_t lengthInternal(VarLengthLenFieldTag<TParams...>, VarLengthElemTag<TParams...>)
const
293 return lengthInternalIterative();
296 std::size_t lengthInternalIterative()
const
298 std::size_t result = 0U;
299 for (
auto& elem : BaseImpl::getValue()) {
300 result += elementLength(elem);
305 template<
typename... TParams>
306 std::size_t elementLengthInternal(
const ElementType& elem, FixedLengthLenFieldTag<TParams...>)
const
308 return LenField::minLength() + BaseImpl::elementLength(elem);
311 template <
typename... TParams>
312 std::size_t elementLengthInternal(
const ElementType& elem, VarLengthLenFieldTag<TParams...>)
const
315 auto origElemLength = BaseImpl::elementLength(elem);
316 auto elemLength = std::min(origElemLength, std::size_t(MaxAllowedElemLength));
317 lenField.setValue(elemLength);
318 return lenField.length() + origElemLength;
321 template <
typename TIter>
322 static void advanceWriteIterator(TIter& iter, std::size_t len)
324 using IterType =
typename std::decay<
decltype(iter)>::type;
325 using ByteType =
typename std::iterator_traits<IterType>::value_type;
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
This file contain definition of error statuses used by comms module.
comms::option::def::SequenceElemSerLengthFieldPrefix< TField, TReadErrorStatus > SequenceElemSerLengthFieldPrefix
Same as comms::option::def::SequenceElemSerLengthFieldPrefix.
Definition options.h:1574
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:19
@ Success
Used to indicate successful outcome of the operation.
@ InvalidMsgData
Used to indicate that a message has invalid data.
Replacement to some types from standard type_traits.