18#include "comms/field/details/VersionStorage.h"
19#include "comms/field/details/FieldOpHelpers.h"
20#include "comms/field/details/MembersVersionDependency.h"
21#include "comms/details/tag.h"
23#include "CommonFuncs.h"
25COMMS_MSVC_WARNING_PUSH
26COMMS_MSVC_WARNING_DISABLE(4324)
41class VariantFieldConstructHelper
44 VariantFieldConstructHelper(
void* storage) : storage_(storage) {}
46 template <std::
size_t TIdx,
typename TField>
47 void operator()()
const
49 new (storage_) TField;
52 void* storage_ =
nullptr;
56class VariantLengthCalcHelper
59 VariantLengthCalcHelper(std::size_t& len,
const void* storage)
65 template <std::
size_t TIdx,
typename TField>
68 len_ =
reinterpret_cast<const TField*
>(storage_)->length();
77class VariantFieldCopyConstructHelper
80 VariantFieldCopyConstructHelper(
void* storage,
const void* other) : storage_(storage), other_(other) {}
82 template <std::
size_t TIdx,
typename TField>
83 void operator()()
const
85 new (storage_) TField(*(
reinterpret_cast<const TField*
>(other_)));
89 void* storage_ =
nullptr;
90 const void* other_ =
nullptr;
94class VariantFieldMoveConstructHelper
97 VariantFieldMoveConstructHelper(
void* storage,
void* other) : storage_(storage), other_(other) {}
99 template <std::
size_t TIdx,
typename TField>
100 void operator()()
const
102 new (storage_) TField(std::move(*(
reinterpret_cast<const TField*
>(other_))));
106 void* storage_ =
nullptr;
107 void* other_ =
nullptr;
111class VariantFieldDestructHelper
114 VariantFieldDestructHelper(
void* storage) : storage_(storage) {}
116 template <std::
size_t TIdx,
typename TField>
117 void operator()()
const
119 reinterpret_cast<TField*
>(storage_)->~TField();
122 void* storage_ =
nullptr;
125template <
typename...>
126class VariantFieldValidCheckHelper
129 VariantFieldValidCheckHelper(
bool& result,
const void* storage)
135 template <std::
size_t TIdx,
typename TField>
138 result_ =
reinterpret_cast<const TField*
>(storage_)->valid();
143 const void* storage_;
146template <
typename...>
147class VariantFieldRefreshHelper
150 VariantFieldRefreshHelper(
bool& result,
void* storage)
156 template <std::
size_t TIdx,
typename TField>
159 result_ =
reinterpret_cast<TField*
>(storage_)->refresh();
164 void* storage_ =
nullptr;
167template <
typename TFunc>
168class VariantExecHelper
170 static_assert(std::is_lvalue_reference<TFunc>::value || std::is_rvalue_reference<TFunc>::value,
171 "Wrong type of template parameter");
173 template <
typename U>
174 VariantExecHelper(
void* storage, U&& func) : storage_(storage), func_(
std::forward<U>(func)) {}
176 template <std::
size_t TIdx,
typename TField>
181 func_.operator()<TIdx>(*(
reinterpret_cast<TField*
>(storage_)));
183 func_.template operator()<TIdx>(*(
reinterpret_cast<TField*
>(storage_)));
187 void* storage_ =
nullptr;
191template <
typename TFunc>
192class VariantConstExecHelper
194 static_assert(std::is_lvalue_reference<TFunc>::value || std::is_rvalue_reference<TFunc>::value,
195 "Wrong type of template parameter");
197 template <
typename U>
198 VariantConstExecHelper(
const void* storage, U&& func) : storage_(storage), func_(
std::forward<U>(func)) {}
200 template <std::
size_t TIdx,
typename TField>
205 func_.operator()<TIdx>(*(
reinterpret_cast<const TField*
>(storage_)));
207 func_.template operator()<TIdx>(*(
reinterpret_cast<const TField*
>(storage_)));
211 const void* storage_ =
nullptr;
216template <
typename TIter,
typename TVerBase,
bool TVerDependent>
217class VariantReadHelper
219 template <
typename... TParams>
220 using VersionDependentTag = comms::details::tag::Tag1<>;
222 template <
typename... TParams>
223 using NoVersionDependencyTag = comms::details::tag::Tag2<>;
225 template <
typename... TParams>
227 typename comms::util::LazyShallowConditional<
231 NoVersionDependencyTag
248 using IterType =
typename std::decay<
decltype(iter)>::type;
249 using IterCategory =
typename std::iterator_traits<IterType>::iterator_category;
250 static_assert(std::is_base_of<std::random_access_iterator_tag, IterCategory>::value,
251 "Variant field only supports read with random access iterators");
256 template <
typename TField>
263 auto* field =
new (storage_) TField;
264 updateMemberVersionInternal(*field, VersionTag<>());
266 auto iterTmp = iter_;
267 auto es = field->read(iterTmp, len_);
271 readComplete_ =
true;
286 template <
typename TField,
typename... TParams>
287 void updateMemberVersionInternal(TField& field, NoVersionDependencyTag<TParams...>)
289 static_cast<void>(field);
292 template <
typename TField,
typename... TParams>
293 void updateMemberVersionInternal(TField& field, VersionDependentTag<TParams...>)
295 field.setVersion(verBase_.getVersion());
301 std::size_t len_ = 0;
302 void* storage_ =
nullptr;
304 bool readComplete_ =
false;
307template <
typename TIter>
308class VariantFieldWriteHelper
311 VariantFieldWriteHelper(ErrorStatus& es, TIter& iter, std::size_t len,
const void* storage)
319 template <std::
size_t TIdx,
typename TField>
322 es_ =
reinterpret_cast<const TField*
>(storage_)->write(iter_, len_);
328 std::size_t len_ = 0U;
329 const void* storage_ =
nullptr;
332template <
typename TIter>
333class VariantWriteNoStatusHelper
336 VariantWriteNoStatusHelper(TIter& iter,
const void* storage)
342 template <std::
size_t TIdx,
typename TField>
345 reinterpret_cast<const TField*
>(storage_)->writeNoStatus(iter_);
350 const void* storage_ =
nullptr;
353template <
typename TVersionType>
354class VariantSetVersionHelper
357 VariantSetVersionHelper(TVersionType version,
bool& updated,
void* storage)
364 template <std::
size_t TIdx,
typename TField>
367 updated_ =
reinterpret_cast<TField*
>(storage_)->setVersion(version_) || updated_;
371 TVersionType version_ = TVersionType();
373 void* storage_ =
nullptr;
377class VariantCanWriteHelper
380 VariantCanWriteHelper(
bool& result,
const void* storage)
386 template <std::
size_t TIdx,
typename TField>
389 result_ =
reinterpret_cast<const TField*
>(storage_)->canWrite();
394 const void* storage_;
397template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
398struct VariantVersionStorageBaseHelper;
400template <
typename TFieldBase,
typename... TMembers>
401struct VariantVersionStorageBaseHelper<TFieldBase,
comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
404 typename comms::util::LazyShallowConditional<
405 CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value
407 comms::field::details::VersionStorage,
408 comms::util::EmptyStruct,
409 typename TFieldBase::VersionType
413template <
typename TFieldBase,
typename... TMembers>
414struct VariantVersionStorageBaseHelper<TFieldBase,
comms::field::details::MembersVersionDependency_Independent, TMembers...>
416 using Type = comms::util::EmptyStruct<>;
419template <
typename TFieldBase,
typename... TMembers>
420struct VariantVersionStorageBaseHelper<TFieldBase,
comms::field::details::MembersVersionDependency_Dependent, TMembers...>
422 using Type = comms::field::details::VersionStorage<typename TFieldBase::VersionType>;
425template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
426using VariantVersionStorageBase =
427 typename VariantVersionStorageBaseHelper<TFieldBase, TVersionDependency, TMembers...>::Type;
429template <comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
430struct VariantVersionDependencyDetectHelper;
432template <
typename... TMembers>
433struct VariantVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
435 static constexpr bool Value = CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value;
438template <
typename... TMembers>
439struct VariantVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Independent, TMembers...>
441 static constexpr bool Value =
false;
444template <
typename... TMembers>
445struct VariantVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Dependent, TMembers...>
447 static constexpr bool Value =
true;
453template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename TMembers>
456template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
457class Variant<TFieldBase, TVersionDependency,
std::tuple<TMembers...> > :
459 public details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>
461 using BaseImpl = TFieldBase;
462 using VersionBaseImpl = details::VariantVersionStorageBase<TFieldBase, TVersionDependency, TMembers...>;
465 using Members = std::tuple<TMembers...>;
467 using VersionType =
typename BaseImpl::VersionType;
468 using CommsTag = comms::field::tag::Variant;
470 static const std::size_t MembersCount = std::tuple_size<Members>::value;
471 static_assert(0U < MembersCount,
"ValueType must be non-empty tuple");
474 Variant(
const ValueType& val) : storage_(val) {}
475 Variant(ValueType&& val) : storage_(
std::move(val)) {}
477 Variant(
const Variant& other)
479 if (!other.currentFieldValid()) {
483 comms::util::tupleForSelectedType<Members>(
484 other.memIdx_, details::VariantFieldCopyConstructHelper<>(&storage_, &other.storage_));
486 memIdx_ = other.memIdx_;
489 Variant(Variant&& other)
491 if (!other.currentFieldValid()) {
495 comms::util::tupleForSelectedType<Members>(
496 other.memIdx_, details::VariantFieldMoveConstructHelper<>(&storage_, &other.storage_));
498 memIdx_ = other.memIdx_;
506 Variant& operator=(
const Variant& other)
508 if (
this == &other) {
513 if (!other.currentFieldValid()) {
517 comms::util::tupleForSelectedType<Members>(
518 other.memIdx_, details::VariantFieldCopyConstructHelper<>(&storage_, &other.storage_));
520 memIdx_ = other.memIdx_;
524 Variant& operator=(Variant&& other)
526 if (
this == &other) {
532 if (!other.currentFieldValid()) {
536 comms::util::tupleForSelectedType<Members>(
537 other.memIdx_, details::VariantFieldMoveConstructHelper<>(&storage_, &other.storage_));
539 memIdx_ = other.memIdx_;
543 const ValueType& value()
const
553 const ValueType& getValue()
const
558 template <
typename T>
559 void setValue(T&& val)
561 value() = std::forward<T>(val);
564 std::size_t length()
const
566 if (!currentFieldValid()) {
570 std::size_t len = std::numeric_limits<std::size_t>::max();
571 comms::util::tupleForSelectedType<Members>(memIdx_, details::VariantLengthCalcHelper<>(len, &storage_));
575 static constexpr std::size_t minLength()
580 static constexpr std::size_t maxLength()
582 return CommonFuncs::FieldSelectMaxLengthIntType<TMembers...>::value;
587 if (!currentFieldValid()) {
592 comms::util::tupleForSelectedType<Members>(
593 memIdx_, details::VariantFieldValidCheckHelper<>(val, &storage_));
597 static constexpr bool hasNonDefaultRefresh()
599 return CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TMembers...>::value;
604 if (!currentFieldValid()) {
609 comms::util::tupleForSelectedType<Members>(
610 memIdx_, details::VariantFieldRefreshHelper<>(val, &storage_));
614 template <
typename TIter>
619 comms::util::tupleForEachType<Members>(makeReadHelper(es, iter, len, &storage_,
static_cast<VersionBaseImpl&
>(*
this)));
626 static constexpr bool hasReadNoStatus()
631 template <
typename TIter>
632 void readNoStatus(TIter& iter) =
delete;
634 bool canWrite()
const
636 if (!currentFieldValid()) {
641 comms::util::tupleForSelectedType<Members>(
642 memIdx_, details::VariantCanWriteHelper<>(val, &storage_));
646 template <
typename TIter>
647 ErrorStatus write(TIter& iter, std::size_t len)
const
649 if (!currentFieldValid()) {
653 auto es = ErrorStatus::NumOfErrorStatuses;
654 comms::util::tupleForSelectedType<Members>(memIdx_, makeWriteHelper(es, iter, len, &storage_));
658 static constexpr bool hasWriteNoStatus()
660 return comms::util::tupleTypeAccumulate<Members>(
661 true, comms::field::details::FieldHasWriteNoStatusHelper<>());
664 template <
typename TIter>
665 void writeNoStatus(TIter& iter)
const
667 if (!currentFieldValid()) {
671 comms::util::tupleForSelectedType<Members>(memIdx_, makeWriteNoStatusHelper(iter, &storage_));
675 std::size_t currentField()
const
680 void selectField(std::size_t idx)
682 if (idx == memIdx_) {
687 if (!isIdxValid(idx)) {
691 comms::util::tupleForSelectedType<Members>(
692 idx, details::VariantFieldConstructHelper<>(&storage_));
696 template <
typename TFunc>
697 void currentFieldExec(TFunc&& func)
699 if (!currentFieldValid()) {
700 static constexpr bool Invalid_field_execution =
false;
701 static_cast<void>(Invalid_field_execution);
706 comms::util::tupleForSelectedType<Members>(memIdx_, makeExecHelper(std::forward<TFunc>(func)));
709 template <
typename TFunc>
710 void currentFieldExec(TFunc&& func)
const
712 if (!currentFieldValid()) {
713 static constexpr bool Invalid_field_execution =
false;
714 static_cast<void>(Invalid_field_execution);
719 comms::util::tupleForSelectedType<Members>(memIdx_, makeConstExecHelper(std::forward<TFunc>(func)));
722 template <std::size_t TIdx,
typename... TArgs>
723 typename std::tuple_element<TIdx, Members>::type& initField(TArgs&&... args)
725 static_assert(isIdxValid(TIdx),
"Only valid field index can be used");
728 using FieldType =
typename std::tuple_element<TIdx, Members>::type;
729 new (&storage_)
FieldType(std::forward<TArgs>(args)...);
731 updateVersionInternal(VersionTag<>());
732 return reinterpret_cast<FieldType&
>(storage_);
735 template <std::
size_t TIdx>
738 static_assert(isIdxValid(TIdx),
"Only valid field index can be used");
741 using FieldType =
typename std::tuple_element<TIdx, Members>::type;
743 memIdx_ = MembersCount;
746 template <std::
size_t TIdx>
747 typename std::tuple_element<TIdx, Members>::type& accessField()
749 static_assert(isIdxValid(TIdx),
"Only valid field index can be used");
752 using FieldType =
typename std::tuple_element<TIdx, Members>::type;
753 return reinterpret_cast<FieldType&
>(storage_);
756 template <std::
size_t TIdx>
757 const typename std::tuple_element<TIdx, Members>::type& accessField()
const
759 static_assert(isIdxValid(TIdx),
"Something is wrong");
762 using FieldType =
typename std::tuple_element<TIdx, Members>::type;
763 return reinterpret_cast<const FieldType&
>(storage_);
766 bool currentFieldValid()
const
768 return isIdxValid(memIdx_);
777 static constexpr bool isVersionDependent()
779 return details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value;
782 bool setVersion(VersionType version)
784 return setVersionInternal(version, VersionTag<>());
789 return getVersionInternal(VersionTag<>());
793 template <
typename... TParams>
794 using VersionDependentTag = comms::details::tag::Tag1<>;
796 template <
typename... TParams>
797 using NoVersionDependencyTag = comms::details::tag::Tag2<>;
799 template <
typename... TParams>
800 using ForcedVersionDependencyTag = comms::details::tag::Tag3<>;
802 template <
typename... TParams>
803 using NoForcedVersionDependencyTag = comms::details::tag::Tag4<>;
805 template <
typename... TParams>
807 typename comms::util::LazyShallowConditional<
808 details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value
811 NoVersionDependencyTag
814 template <
typename TFunc>
815 auto makeExecHelper(TFunc&& func) -> details::VariantExecHelper<decltype(std::forward<TFunc>(func))>
817 using FuncType =
decltype(std::forward<TFunc>(func));
818 return details::VariantExecHelper<FuncType>(&storage_, std::forward<TFunc>(func));
821 template <
typename TFunc>
822 auto makeConstExecHelper(TFunc&& func)
const -> details::VariantConstExecHelper<decltype(std::forward<TFunc>(func))>
824 using FuncType =
decltype(std::forward<TFunc>(func));
825 return details::VariantConstExecHelper<FuncType>(&storage_, std::forward<TFunc>(func));
828 template <
typename TIter,
typename TVerBase>
829 details::VariantReadHelper<TIter, TVerBase, details::VariantVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value>
838 static constexpr bool VerDependent = isVersionDependent();
840 details::VariantReadHelper<TIter, TVerBase, VerDependent>(
841 memIdx_, es, iter, len, storage, verBase);
844 template <
typename TIter>
845 static details::VariantFieldWriteHelper<TIter> makeWriteHelper(
comms::ErrorStatus& es, TIter& iter, std::size_t len,
const void* storage)
847 return details::VariantFieldWriteHelper<TIter>(es, iter, len, storage);
850 template <
typename TIter>
851 static details::VariantWriteNoStatusHelper<TIter> makeWriteNoStatusHelper(TIter& iter,
const void* storage)
853 return details::VariantWriteNoStatusHelper<TIter>(iter, storage);
858 if (currentFieldValid()) {
859 comms::util::tupleForSelectedType<Members>(
860 memIdx_, details::VariantFieldDestructHelper<>(&storage_));
861 memIdx_ = MembersCount;
865 static constexpr bool isIdxValid(std::size_t idx)
867 return idx < MembersCount;
870 template <
typename... TParams>
871 bool setVersionInternal(VersionType version, NoVersionDependencyTag<TParams...>)
877 template <
typename... TParams>
878 bool setVersionInternal(VersionType version, VersionDependentTag<TParams...>)
880 VersionBaseImpl::version_ =
version;
881 bool updated =
false;
882 if (currentFieldValid()) {
883 comms::util::tupleForSelectedType<Members>(
884 memIdx_, details::VariantSetVersionHelper<VersionType>(version, updated, &storage_));
890 template <
typename... TParams>
891 VersionType getVersionInternal(VersionDependentTag<TParams...>)
const
893 return VersionBaseImpl::version_;;
896 template <
typename... TParams>
897 void updateVersionInternal(NoVersionDependencyTag<TParams...>)
901 template <
typename... TParams>
902 void updateVersionInternal(VersionDependentTag<TParams...>)
904 setVersion(VersionBaseImpl::version_);
907 alignas(8) ValueType storage_;
908 std::size_t memIdx_ = MembersCount;
917COMMS_MSVC_WARNING_POP
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
Contains various compiler related definitions.
This file contain definition of error statuses used by comms module.
Contains various tuple type manipulation classes and functions.
Contains definition of various tag classes.
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition options.h:1797
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition options.h:1463
typename TupleAsAlignedUnion< TTuple >::Type TupleAsAlignedUnionT
Alias to TupleAsAlignedUnion::Type.
Definition Tuple.h:185
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.
@ NumOfErrorStatuses
Number of supported error statuses, must be last.
constexpr unsigned version()
Version of the COMMS library as single numeric value.
Definition version.h:64
Replacement to some types from standard type_traits.