14#include "comms/util/SizeToType.h"
17#include "comms/field/details/FieldOpHelpers.h"
18#include "comms/field/details/MembersVersionDependency.h"
24#include "CommonFuncs.h"
38template <
typename TSerializedType>
39class BitfieldReadHelper
42 BitfieldReadHelper(TSerializedType val,
ErrorStatus& es)
48 template <std::
size_t TIdx,
typename TFieldParam>
49 void operator()(TFieldParam&& field)
55 using FieldType =
typename std::decay<
decltype(field)>::type;
56 static const auto FieldBitLength =
57 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
58 static const auto Mask =
59 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
62 static_cast<TSerializedType
>((value_ >> pos_) & Mask);
64 pos_ += FieldBitLength;
66 static_assert(FieldType::minLength() == FieldType::maxLength(),
67 "Bitfield doesn't support members with variable length");
69 static const std::size_t MaxLength = FieldType::maxLength();
70 std::uint8_t buf[MaxLength];
71 auto* writeIter = &buf[0];
72 using FieldEndian =
typename FieldType::Endian;
73 comms::util::writeData<MaxLength>(fieldSerValue, writeIter, FieldEndian());
75 const auto* readIter = &buf[0];
76 es_ = field.read(readIter, MaxLength);
80 TSerializedType value_ = TSerializedType();
82 std::size_t pos_ = 0U;
85template <
typename TSerializedType>
86class BitfieldReadNoStatusHelper
89 BitfieldReadNoStatusHelper(TSerializedType val)
92 template <std::
size_t TIdx,
typename TFieldParam>
93 void operator()(TFieldParam&& field)
95 using FieldType =
typename std::decay<
decltype(field)>::type;
96 static const auto FieldBitLength =
97 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
98 static const auto Mask =
99 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
102 static_cast<TSerializedType
>((value_ >> pos_) & Mask);
103 pos_ += FieldBitLength;
105 static_assert(FieldType::minLength() == FieldType::maxLength(),
106 "Bitfield doesn't support members with variable length");
108 static const std::size_t MaxLength = FieldType::maxLength();
109 std::uint8_t buf[MaxLength];
110 auto* writeIter = &buf[0];
111 using FieldEndian =
typename FieldType::Endian;
112 comms::util::writeData<MaxLength>(fieldSerValue, writeIter, FieldEndian());
114 const auto* readIter = &buf[0];
115 field.readNoStatus(readIter);
119 TSerializedType value_ = TSerializedType();
120 std::size_t pos_ = 0U;
123template <
typename TSerializedType>
124class BitfieldWriteHelper
127 BitfieldWriteHelper(TSerializedType& val,
ErrorStatus& es)
131 template <std::
size_t TIdx,
typename TFieldParam>
132 void operator()(TFieldParam&& field)
138 using FieldType =
typename std::decay<
decltype(field)>::type;
140 static_assert(FieldType::minLength() == FieldType::maxLength(),
141 "Bitfield supports fixed length members only.");
143 static const std::size_t MaxLength = FieldType::maxLength();
144 std::uint8_t buf[MaxLength];
145 auto* writeIter = &buf[0];
146 es_ = field.write(writeIter, MaxLength);
151 using FieldEndian =
typename FieldType::Endian;
152 const auto* readIter = &buf[0];
153 auto fieldSerValue = comms::util::readData<TSerializedType, MaxLength>(readIter, FieldEndian());
155 static const auto FieldBitLength =
156 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
157 static const auto Mask =
158 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
160 static const auto ClearMask =
static_cast<TSerializedType
>(~(Mask << pos_));
163 static_cast<TSerializedType
>(
164 (
static_cast<TSerializedType
>(fieldSerValue) & Mask) << pos_);
168 pos_ += FieldBitLength;
173 TSerializedType& value_;
175 std::size_t pos_ = 0U;
178template <
typename TSerializedType>
179class BitfieldWriteNoStatusHelper
182 BitfieldWriteNoStatusHelper(TSerializedType& val)
185 template <std::
size_t TIdx,
typename TFieldParam>
186 void operator()(TFieldParam&& field)
189 using FieldType =
typename std::decay<
decltype(field)>::type;
191 static_assert(FieldType::minLength() == FieldType::maxLength(),
192 "Bitfield supports fixed length members only.");
194 static const std::size_t MaxLength = FieldType::maxLength();
195 std::uint8_t buf[MaxLength];
196 auto* writeIter = &buf[0];
197 field.writeNoStatus(writeIter);
199 using FieldEndian =
typename FieldType::Endian;
200 const auto* readIter = &buf[0];
201 auto fieldSerValue = comms::util::readData<TSerializedType, MaxLength>(readIter, FieldEndian());
203 static const auto FieldBitLength =
204 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
206 static const auto Mask =
207 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
209 static const auto ClearMask =
static_cast<TSerializedType
>(~(Mask << pos_));
212 static_cast<TSerializedType
>(
213 (
static_cast<TSerializedType
>(fieldSerValue) & Mask) << pos_);
217 pos_ += FieldBitLength;
221 TSerializedType& value_;
222 std::size_t pos_ = 0U;
225template <comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
226struct BitfieldVersionDependencyDetectHelper;
228template <
typename... TMembers>
229struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
231 static constexpr bool Value = CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value;
234template <
typename... TMembers>
235struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Independent, TMembers...>
237 static constexpr bool Value =
false;
240template <
typename... TMembers>
241struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Dependent, TMembers...>
243 static constexpr bool Value =
true;
248template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename TMembers>
251template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
252class Bitfield<TFieldBase, TVersionDependency,
std::tuple<TMembers...> > :
public TFieldBase
254 using BaseImpl = TFieldBase;
255 using Members = std::tuple<TMembers...>;
258 1U < std::tuple_size<Members>::value,
259 "Number of members is expected to be at least 2.");
262 static const std::size_t TotalBits = CommonFuncs::FieldSumTotalBitLengthIntType<TMembers...>::value;
264 (TotalBits % std::numeric_limits<std::uint8_t>::digits) == 0,
265 "Wrong number of total bits");
267 static const std::size_t Length = TotalBits / std::numeric_limits<std::uint8_t>::digits;
268 static_assert(0U < Length,
"Serialised length is expected to be greater than 0");
269 using SerializedType =
typename comms::util::SizeToType<Length, false>::Type;
271 using FixedIntValueField =
279 using SimpleIntValueField =
285 using IntValueField =
287 ((Length & (Length - 1)) == 0)
294 using Endian =
typename BaseImpl::Endian;
295 using VersionType =
typename BaseImpl::VersionType;
296 using ValueType = Members;
297 using CommsTag = comms::field::tag::Bitfield;
299 Bitfield() =
default;
300 explicit Bitfield(
const ValueType& val)
305 explicit Bitfield(ValueType&& val)
306 : members_(
std::move(val))
310 const ValueType& value()
const
320 const ValueType& getValue()
const
325 template <
typename T>
326 void setValue(T&& val)
328 value() = std::forward<T>(val);
331 static constexpr std::size_t length()
336 static constexpr std::size_t minLength()
341 static constexpr std::size_t maxLength()
346 template <
typename TIter>
349 if (size < length()) {
353 auto serValue = BaseImpl::template readData<SerializedType, Length>(iter);
356 members_, details::BitfieldReadHelper<SerializedType>(serValue, es));
360 static constexpr bool hasReadNoStatus()
362 return CommonFuncs::AllFieldsHaveReadNoStatusBoolType<TMembers...>::value;
365 template <
typename TIter>
366 void readNoStatus(TIter& iter)
368 auto serValue = BaseImpl::template readData<SerializedType, Length>(iter);
370 members_, details::BitfieldReadNoStatusHelper<SerializedType>(serValue));
373 bool canWrite()
const
377 value(),
true, comms::field::details::FieldCanWriteCheckHelper<>());
380 template <
typename TIter>
381 ErrorStatus write(TIter& iter, std::size_t size)
const
383 if (size < length()) {
387 SerializedType serValue = 0;
390 members_, details::BitfieldWriteHelper<SerializedType>(serValue, es));
392 comms::util::writeData<Length>(serValue, iter,
Endian());
397 static constexpr bool hasWriteNoStatus()
399 return CommonFuncs::AllFieldsHaveWriteNoStatusBoolType<TMembers...>::value;
402 template <
typename TIter>
403 void writeNoStatus(TIter& iter)
const
405 SerializedType serValue = 0;
407 members_, details::BitfieldWriteNoStatusHelper<SerializedType>(serValue));
408 comms::util::writeData<Length>(serValue, iter,
Endian());
411 constexpr bool valid()
const
419 members_,
false, comms::field::details::FieldRefreshHelper<>());
422 template <std::
size_t TIdx>
423 static constexpr std::size_t memberBitLength()
426 TIdx < std::tuple_size<ValueType>::value,
427 "Index exceeds number of fields");
429 using FieldType =
typename std::tuple_element<TIdx, ValueType>::type;
430 return comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
433 static constexpr bool isVersionDependent()
435 return details::BitfieldVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value;
438 static constexpr bool hasNonDefaultRefresh()
440 return CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TMembers...>::value;
443 bool setVersion(VersionType
version)
445 return CommonFuncs::setVersionForMembers(value(),
version);
449 using BaseImpl::readData;
450 using BaseImpl::writeData;
This file contains classes required for generic custom assertion functionality.
This file contain definition of error statuses used by comms module.
Contains definition of comms::field::IntValue.
Contains various tuple type manipulation classes and functions.
Contains functions for raw data access / (de)serialization.
Field that represent integral value.
Definition IntValue.h:72
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
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1438
void tupleForEachWithTemplateParamIdx(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple while providing information about element inde...
Definition Tuple.h:520
constexpr TValue tupleAccumulate(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition Tuple.h:586
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.
constexpr unsigned version()
Version of the COMMS library as single numeric value.
Definition version.h:64
Option used to specify number of bytes that is used for field serialisation.
Definition options.h:280
Replacement to std::conditional.
Definition type_traits.h:28
Replacement to some types from standard type_traits.