16#include "comms/field/basic/CommonFuncs.h"
18#include "comms/details/tag.h"
29template <
typename TLenField, comms::ErrorStatus TStatus,
typename TBase>
32 using BaseImpl = TBase;
33 using LenField = TLenField;
34 static const std::size_t MaxAllowedElemLength =
35 static_cast<std::size_t
>(LenField::maxValue());
37 static_assert(!LenField::isVersionDependent(),
38 "Prefix fields must not be version dependent");
41 using ValueType =
typename BaseImpl::ValueType;
42 using ElementType =
typename BaseImpl::ElementType;
52 : BaseImpl(
std::move(val))
61 std::size_t length()
const
64 typename comms::util::LazyShallowConditional<
65 BaseImpl::minElementLength() == BaseImpl::maxElementLength()
70 return lengthInternal(LenFieldLengthTag<>(), ElemLengthTag());
73 std::size_t elementLength(
const ElementType& elem)
const
75 return elementLengthInternal(elem, LenFieldLengthTag<>());
78 static constexpr std::size_t minLength()
80 return LenField::minLength();
83 static constexpr std::size_t maxLength()
85 return basic::CommonFuncs::maxSupportedLength();
88 static constexpr std::size_t minElementLength()
90 return LenField::minLength() + BaseImpl::minElementLength();
93 static constexpr std::size_t maxElementLength()
95 return LenField::maxLength() + BaseImpl::maxElementLength();
98 template <
typename TIter>
99 ErrorStatus readElement(ElementType& elem, TIter& iter, std::size_t& len)
const
101 auto fromIter = iter;
103 auto es = lenField.read(iter, len);
108 auto diff =
static_cast<std::size_t
>(std::distance(fromIter, iter));
111 if (len < lenField.getValue()) {
115 const auto reqLen =
static_cast<std::size_t
>(lenField.getValue());
116 std::size_t elemLen = reqLen;
117 es = BaseImpl::readElement(elem, iter, elemLen);
127 std::advance(iter, elemLen);
132 template <
typename TIter>
133 void readElementNoStatus(ElementType& elem, TIter& iter)
const =
delete;
135 template <
typename TIter>
138 return basic::CommonFuncs::readSequence(*
this, iter, len);
141 static constexpr bool hasReadNoStatus()
146 template <
typename TIter>
147 void readNoStatus(TIter& iter) =
delete;
149 template <
typename TIter>
150 ErrorStatus readN(std::size_t count, TIter& iter, std::size_t& len)
152 return basic::CommonFuncs::readSequenceN(*
this, count, iter, len);
155 template <
typename TIter>
156 void readNoStatusN(std::size_t count, TIter& iter) =
delete;
158 bool canWriteElement(
const ElementType& elem)
const
160 if (!BaseImpl::canWriteElement(elem)) {
164 auto elemLen = elementLength(elem);
165 if (MaxAllowedElemLength < elemLen) {
170 lenField.setValue(elemLen);
171 return lenField.canWrite();
174 template <
typename TIter>
175 ErrorStatus writeElement(
const ElementType& elem, TIter& iter, std::size_t& len)
const
177 if (!canWriteElement(elem)) {
181 auto elemLength = BaseImpl::elementLength(elem);
183 lenField.setValue(elemLength);
184 auto es = lenField.write(iter, len);
189 len -= lenField.length();
190 return BaseImpl::writeElement(elem, iter, len);
193 template <
typename TIter>
194 static void writeElementNoStatus(
const ElementType& elem, TIter& iter) =
delete;
196 bool canWrite()
const
198 return basic::CommonFuncs::canWriteSequence(*
this);
201 template <
typename TIter>
202 ErrorStatus write(TIter& iter, std::size_t len)
const
204 return basic::CommonFuncs::writeSequence(*
this, iter, len);
207 static constexpr bool hasWriteNoStatus()
212 template <
typename TIter>
213 void writeNoStatus(TIter& iter)
const =
delete;
215 template <
typename TIter>
216 ErrorStatus writeN(std::size_t count, TIter& iter, std::size_t& len)
const
218 return basic::CommonFuncs::writeSequenceN(*
this, count, iter, len);
221 template <
typename TIter>
222 void writeNoStatusN(std::size_t count, TIter& iter)
const =
delete;
226 if (!BaseImpl::valid()) {
230 auto& vec = BaseImpl::getValue();
231 for (
auto& elem : vec) {
232 auto elemLen = BaseImpl::elementLength(elem);
233 if (MaxAllowedElemLength < elemLen) {
242 template <
typename... TParams>
243 using FixedLengthLenFieldTag = comms::details::tag::Tag1<>;
245 template <
typename... TParams>
246 using VarLengthLenFieldTag = comms::details::tag::Tag2<>;
248 template <
typename... TParams>
249 using FixedLengthElemTag = comms::details::tag::Tag3<>;
251 template <
typename... TParams>
252 using VarLengthElemTag = comms::details::tag::Tag4<>;
254 template <
typename...>
255 using LenFieldLengthTag =
256 typename comms::util::LazyShallowConditional<
257 LenField::minLength() == LenField::maxLength()
259 FixedLengthLenFieldTag,
263 template<
typename... TParams>
264 std::size_t lengthInternal(FixedLengthLenFieldTag<TParams...>, FixedLengthElemTag<TParams...>)
const
266 return (LenField::minLength() + BaseImpl::minElementLength()) * BaseImpl::getValue().size();
269 template<
typename... TParams>
270 std::size_t lengthInternal(FixedLengthLenFieldTag<TParams...>, VarLengthElemTag<TParams...>)
const
272 return lengthInternalIterative();
275 template <
typename... TParams>
276 std::size_t lengthInternal(VarLengthLenFieldTag<TParams...>, FixedLengthElemTag<TParams...>)
const
278 auto origElemLen = BaseImpl::minElementLength();
279 auto elemLen = std::min(origElemLen, std::size_t(MaxAllowedElemLength));
281 lenField.setValue(elemLen);
282 return (lenField.length() + origElemLen) * BaseImpl::getValue().size();
285 template <
typename... TParams>
286 std::size_t lengthInternal(VarLengthLenFieldTag<TParams...>, VarLengthElemTag<TParams...>)
const
288 return lengthInternalIterative();
291 std::size_t lengthInternalIterative()
const
293 std::size_t result = 0U;
294 for (
auto& elem : BaseImpl::getValue()) {
295 result += elementLength(elem);
300 template<
typename... TParams>
301 std::size_t elementLengthInternal(
const ElementType& elem, FixedLengthLenFieldTag<TParams...>)
const
303 return LenField::minLength() + BaseImpl::elementLength(elem);
306 template <
typename... TParams>
307 std::size_t elementLengthInternal(
const ElementType& elem, VarLengthLenFieldTag<TParams...>)
const
310 auto origElemLength = BaseImpl::elementLength(elem);
311 auto elemLength = std::min(origElemLength, std::size_t(MaxAllowedElemLength));
312 lenField.setValue(elemLength);
313 return lenField.length() + origElemLength;
316 template <
typename TIter>
317 static void advanceWriteIterator(TIter& iter, std::size_t len)
319 using IterType =
typename std::decay<
decltype(iter)>::type;
320 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:1518
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:17
@ 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.