12#include "comms/field/basic/CommonFuncs.h"
13#include "comms/field/details/FieldOpHelpers.h"
14#include "comms/field/details/MembersVersionDependency.h"
18#include "comms/util/SizeToType.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
>((m_value >> m_pos) & Mask);
64 m_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 m_es = field.read(readIter, MaxLength);
80 TSerializedType m_value = TSerializedType();
82 std::size_t m_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
>((m_value >> m_pos) & Mask);
103 m_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 m_value = TSerializedType();
120 std::size_t m_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 m_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 << m_pos));
163 static_cast<TSerializedType
>(
164 (
static_cast<TSerializedType
>(fieldSerValue) & Mask) << m_pos);
166 m_value &= ClearMask;
167 m_value |= valueMask;
168 m_pos += FieldBitLength;
172 TSerializedType& m_value;
174 std::size_t m_pos = 0U;
177template <
typename TSerializedType>
178class BitfieldWriteNoStatusHelper
181 BitfieldWriteNoStatusHelper(TSerializedType& val)
184 template <std::
size_t TIdx,
typename TFieldParam>
185 void operator()(TFieldParam&& field)
188 using FieldType =
typename std::decay<
decltype(field)>::type;
190 static_assert(FieldType::minLength() == FieldType::maxLength(),
191 "Bitfield supports fixed length members only.");
193 static const std::size_t MaxLength = FieldType::maxLength();
194 std::uint8_t buf[MaxLength];
195 auto* writeIter = &buf[0];
196 field.writeNoStatus(writeIter);
198 using FieldEndian =
typename FieldType::Endian;
199 const auto* readIter = &buf[0];
200 auto fieldSerValue = comms::util::readData<TSerializedType, MaxLength>(readIter, FieldEndian());
202 static const auto FieldBitLength =
203 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
205 static const auto Mask =
206 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
208 static const auto ClearMask =
static_cast<TSerializedType
>(~(Mask << m_pos));
211 static_cast<TSerializedType
>(
212 (
static_cast<TSerializedType
>(fieldSerValue) & Mask) << m_pos);
214 m_value &= ClearMask;
215 m_value |= valueMask;
216 m_pos += FieldBitLength;
220 TSerializedType& m_value;
221 std::size_t m_pos = 0U;
224template <comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
225struct BitfieldVersionDependencyDetectHelper;
227template <
typename... TMembers>
228struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
230 static constexpr bool Value = CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value;
233template <
typename... TMembers>
234struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Independent, TMembers...>
236 static constexpr bool Value =
false;
239template <
typename... TMembers>
240struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Dependent, TMembers...>
242 static constexpr bool Value =
true;
247template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename TMembers>
250template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
251class Bitfield<TFieldBase, TVersionDependency,
std::tuple<TMembers...> > :
public TFieldBase
253 using BaseImpl = TFieldBase;
254 using Members = std::tuple<TMembers...>;
257 1U < std::tuple_size<Members>::value,
258 "Number of members is expected to be at least 2.");
260 static const std::size_t TotalBits = CommonFuncs::FieldSumTotalBitLengthIntType<TMembers...>::value;
262 (TotalBits % std::numeric_limits<std::uint8_t>::digits) == 0,
263 "Wrong number of total bits");
265 static const std::size_t Length = TotalBits / std::numeric_limits<std::uint8_t>::digits;
266 static_assert(0U < Length,
"Serialised length is expected to be greater than 0");
267 using SerializedType =
typename comms::util::SizeToType<Length, false>::Type;
269 using FixedIntValueField =
276 using SimpleIntValueField =
282 using IntValueField =
284 ((Length & (Length - 1)) == 0)
291 using Endian =
typename BaseImpl::Endian;
292 using VersionType =
typename BaseImpl::VersionType;
293 using ValueType = Members;
294 using CommsTag = comms::field::tag::Bitfield;
296 Bitfield() =
default;
297 explicit Bitfield(
const ValueType& val)
302 explicit Bitfield(ValueType&& val)
303 : m_members(
std::move(val))
307 const ValueType& value()
const
317 const ValueType& getValue()
const
322 template <
typename T>
323 void setValue(T&& val)
325 value() = std::forward<T>(val);
328 static constexpr std::size_t length()
333 static constexpr std::size_t minLength()
338 static constexpr std::size_t maxLength()
343 template <
typename TIter>
346 if (size < length()) {
350 auto serValue = BaseImpl::template readData<SerializedType, Length>(iter);
353 m_members, details::BitfieldReadHelper<SerializedType>(serValue, es));
357 static constexpr bool hasReadNoStatus()
359 return CommonFuncs::AllFieldsHaveReadNoStatusBoolType<TMembers...>::value;
362 template <
typename TIter>
363 void readNoStatus(TIter& iter)
365 auto serValue = BaseImpl::template readData<SerializedType, Length>(iter);
367 m_members, details::BitfieldReadNoStatusHelper<SerializedType>(serValue));
370 bool canWrite()
const
374 value(),
true, comms::field::details::FieldCanWriteCheckHelper<>());
377 template <
typename TIter>
378 ErrorStatus write(TIter& iter, std::size_t size)
const
380 if (size < length()) {
384 SerializedType serValue = 0;
387 m_members, details::BitfieldWriteHelper<SerializedType>(serValue, es));
389 comms::util::writeData<Length>(serValue, iter,
Endian());
394 static constexpr bool hasWriteNoStatus()
396 return CommonFuncs::AllFieldsHaveWriteNoStatusBoolType<TMembers...>::value;
399 template <
typename TIter>
400 void writeNoStatus(TIter& iter)
const
402 SerializedType serValue = 0;
404 m_members, details::BitfieldWriteNoStatusHelper<SerializedType>(serValue));
405 comms::util::writeData<Length>(serValue, iter,
Endian());
408 constexpr bool valid()
const
416 m_members,
false, comms::field::details::FieldRefreshHelper<>());
419 template <std::
size_t TIdx>
420 static constexpr std::size_t memberBitLength()
423 TIdx < std::tuple_size<ValueType>::value,
424 "Index exceeds number of fields");
426 using FieldType =
typename std::tuple_element<TIdx, ValueType>::type;
427 return comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
430 static constexpr bool isVersionDependent()
432 return details::BitfieldVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value;
435 static constexpr bool hasNonDefaultRefresh()
437 return CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TMembers...>::value;
440 bool setVersion(VersionType
version)
442 return CommonFuncs::setVersionForMembers(value(),
version);
446 using BaseImpl::readData;
447 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:76
Contains definition of various tag classes.
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition options.h:1928
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition options.h:1503
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1471
void tupleForEachWithTemplateParamIdx(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple while providing information about element inde...
Definition Tuple.h:519
constexpr TValue tupleAccumulate(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition Tuple.h:584
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:278
Replacement to std::conditional.
Definition type_traits.h:29
Replacement to some types from standard type_traits.