14#include "comms/field/basic/CommonFuncs.h"
15#include "comms/field/details/FieldOpHelpers.h"
16#include "comms/field/details/MembersVersionDependency.h"
20#include "comms/util/SizeToType.h"
43template <
typename TSerializedType>
44class BitfieldReadHelper
47 BitfieldReadHelper(TSerializedType val,
ErrorStatus& es)
53 template <std::
size_t TIdx,
typename TFieldParam>
54 void operator()(TFieldParam&& field)
60 using FieldType =
typename std::decay<
decltype(field)>::type;
61 static const auto FieldBitLength =
62 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
63 static const auto Mask =
64 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
67 static_cast<TSerializedType
>((m_value >> m_pos) & Mask);
69 m_pos += FieldBitLength;
71 static_assert(FieldType::minLength() == FieldType::maxLength(),
72 "Bitfield doesn't support members with variable length");
74 static const std::size_t MaxLength = FieldType::maxLength();
75 std::uint8_t buf[MaxLength];
76 auto* writeIter = &buf[0];
77 using FieldEndian =
typename FieldType::Endian;
78 comms::util::writeData<MaxLength>(fieldSerValue, writeIter, FieldEndian());
80 const auto* readIter = &buf[0];
81 m_es = field.read(readIter, MaxLength);
85 TSerializedType m_value = TSerializedType();
87 std::size_t m_pos = 0U;
90template <
typename TSerializedType>
91class BitfieldReadNoStatusHelper
94 BitfieldReadNoStatusHelper(TSerializedType val)
97 template <std::
size_t TIdx,
typename TFieldParam>
98 void operator()(TFieldParam&& field)
100 using FieldType =
typename std::decay<
decltype(field)>::type;
101 static const auto FieldBitLength =
102 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
103 static const auto Mask =
104 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
107 static_cast<TSerializedType
>((m_value >> m_pos) & Mask);
108 m_pos += FieldBitLength;
110 static_assert(FieldType::minLength() == FieldType::maxLength(),
111 "Bitfield doesn't support members with variable length");
113 static const std::size_t MaxLength = FieldType::maxLength();
114 std::uint8_t buf[MaxLength];
115 auto* writeIter = &buf[0];
116 using FieldEndian =
typename FieldType::Endian;
117 comms::util::writeData<MaxLength>(fieldSerValue, writeIter, FieldEndian());
119 const auto* readIter = &buf[0];
120 field.readNoStatus(readIter);
124 TSerializedType m_value = TSerializedType();
125 std::size_t m_pos = 0U;
128template <
typename TSerializedType>
129class BitfieldWriteHelper
132 BitfieldWriteHelper(TSerializedType& val,
ErrorStatus& es)
136 template <std::
size_t TIdx,
typename TFieldParam>
137 void operator()(TFieldParam&& field)
143 using FieldType =
typename std::decay<
decltype(field)>::type;
145 static_assert(FieldType::minLength() == FieldType::maxLength(),
146 "Bitfield supports fixed length members only.");
148 static const std::size_t MaxLength = FieldType::maxLength();
149 std::uint8_t buf[MaxLength];
150 auto* writeIter = &buf[0];
151 m_es = field.write(writeIter, MaxLength);
156 using FieldEndian =
typename FieldType::Endian;
157 const auto* readIter = &buf[0];
158 auto fieldSerValue = comms::util::readData<TSerializedType, MaxLength>(readIter, FieldEndian());
160 static const auto FieldBitLength =
161 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
162 static const auto Mask =
163 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
165 static const auto ClearMask =
static_cast<TSerializedType
>(~(Mask << m_pos));
168 static_cast<TSerializedType
>(
169 (
static_cast<TSerializedType
>(fieldSerValue) & Mask) << m_pos);
171 m_value &= ClearMask;
172 m_value |= valueMask;
173 m_pos += FieldBitLength;
177 TSerializedType& m_value;
179 std::size_t m_pos = 0U;
182template <
typename TSerializedType>
183class BitfieldWriteNoStatusHelper
186 BitfieldWriteNoStatusHelper(TSerializedType& val)
189 template <std::
size_t TIdx,
typename TFieldParam>
190 void operator()(TFieldParam&& field)
193 using FieldType =
typename std::decay<
decltype(field)>::type;
195 static_assert(FieldType::minLength() == FieldType::maxLength(),
196 "Bitfield supports fixed length members only.");
198 static const std::size_t MaxLength = FieldType::maxLength();
199 std::uint8_t buf[MaxLength];
200 auto* writeIter = &buf[0];
201 field.writeNoStatus(writeIter);
203 using FieldEndian =
typename FieldType::Endian;
204 const auto* readIter = &buf[0];
205 auto fieldSerValue = comms::util::readData<TSerializedType, MaxLength>(readIter, FieldEndian());
207 static const auto FieldBitLength =
208 comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
210 static const auto Mask =
211 (
static_cast<TSerializedType
>(1) << FieldBitLength) - 1;
213 static const auto ClearMask =
static_cast<TSerializedType
>(~(Mask << m_pos));
216 static_cast<TSerializedType
>(
217 (
static_cast<TSerializedType
>(fieldSerValue) & Mask) << m_pos);
219 m_value &= ClearMask;
220 m_value |= valueMask;
221 m_pos += FieldBitLength;
225 TSerializedType& m_value;
226 std::size_t m_pos = 0U;
229template <comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
230struct BitfieldVersionDependencyDetectHelper;
232template <
typename... TMembers>
233struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_NotSpecified, TMembers...>
235 static constexpr bool Value = CommonFuncs::IsAnyFieldVersionDependentBoolType<TMembers...>::value;
238template <
typename... TMembers>
239struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Independent, TMembers...>
241 static constexpr bool Value =
false;
244template <
typename... TMembers>
245struct BitfieldVersionDependencyDetectHelper<
comms::field::details::MembersVersionDependency_Dependent, TMembers...>
247 static constexpr bool Value =
true;
252template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename TMembers>
255template <
typename TFieldBase, comms::field::details::MembersVersionDependency TVersionDependency,
typename... TMembers>
256class Bitfield<TFieldBase, TVersionDependency,
std::tuple<TMembers...> > :
public TFieldBase
258 using BaseImpl = TFieldBase;
259 using Members = std::tuple<TMembers...>;
262 1U < std::tuple_size<Members>::value,
263 "Number of members is expected to be at least 2.");
265 static const std::size_t TotalBits = CommonFuncs::FieldSumTotalBitLengthIntType<TMembers...>::value;
267 (TotalBits % std::numeric_limits<std::uint8_t>::digits) == 0,
268 "Wrong number of total bits");
270 static const std::size_t Length = TotalBits / std::numeric_limits<std::uint8_t>::digits;
271 static_assert(0U < Length,
"Serialised length is expected to be greater than 0");
272 using SerializedType =
typename comms::util::SizeToType<Length, false>::Type;
274 using FixedIntValueField =
281 using SimpleIntValueField =
287 using IntValueField =
289 ((Length & (Length - 1)) == 0)
296 using Endian =
typename BaseImpl::Endian;
297 using VersionType =
typename BaseImpl::VersionType;
298 using ValueType = Members;
299 using CommsTag = comms::field::tag::Bitfield;
301 Bitfield() =
default;
302 explicit Bitfield(
const ValueType& val)
307 explicit Bitfield(ValueType&& val)
308 : m_members(
std::move(val))
312 const ValueType& value()
const
322 const ValueType& getValue()
const
327 template <
typename T>
328 void setValue(T&& val)
330 value() = std::forward<T>(val);
333 static constexpr std::size_t length()
338 static constexpr std::size_t minLength()
343 static constexpr std::size_t maxLength()
348 template <
typename TIter>
351 if (size < length()) {
355 auto serValue = BaseImpl::template readData<SerializedType, Length>(iter);
358 m_members, details::BitfieldReadHelper<SerializedType>(serValue, es));
362 static constexpr bool hasReadNoStatus()
364 return CommonFuncs::AllFieldsHaveReadNoStatusBoolType<TMembers...>::value;
367 template <
typename TIter>
368 void readNoStatus(TIter& iter)
370 auto serValue = BaseImpl::template readData<SerializedType, Length>(iter);
372 m_members, details::BitfieldReadNoStatusHelper<SerializedType>(serValue));
375 bool canWrite()
const
379 value(),
true, comms::field::details::FieldCanWriteCheckHelper<>());
382 template <
typename TIter>
383 ErrorStatus write(TIter& iter, std::size_t size)
const
385 if (size < length()) {
389 SerializedType serValue = 0;
392 m_members, details::BitfieldWriteHelper<SerializedType>(serValue, es));
394 comms::util::writeData<Length>(serValue, iter,
Endian());
399 static constexpr bool hasWriteNoStatus()
401 return CommonFuncs::AllFieldsHaveWriteNoStatusBoolType<TMembers...>::value;
404 template <
typename TIter>
405 void writeNoStatus(TIter& iter)
const
407 SerializedType serValue = 0;
409 m_members, details::BitfieldWriteNoStatusHelper<SerializedType>(serValue));
410 comms::util::writeData<Length>(serValue, iter,
Endian());
413 constexpr bool valid()
const
421 m_members,
false, comms::field::details::FieldRefreshHelper<>());
424 template <std::
size_t TIdx>
425 static constexpr std::size_t memberBitLength()
428 TIdx < std::tuple_size<ValueType>::value,
429 "Index exceeds number of fields");
431 using FieldType =
typename std::tuple_element<TIdx, ValueType>::type;
432 return comms::util::FieldBitLengthIntType<>::template Type<FieldType>::value;
435 static constexpr bool isVersionDependent()
437 return details::BitfieldVersionDependencyDetectHelper<TVersionDependency, TMembers...>::Value;
440 static constexpr bool hasNonDefaultRefresh()
442 return CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TMembers...>::value;
445 bool setVersion(VersionType
version)
447 return CommonFuncs::setVersionForMembers(value(),
version);
451 using BaseImpl::readData;
452 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:79
Contains definition of various tag classes.
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition options.h:1930
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition options.h:1505
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1473
void tupleForEachWithTemplateParamIdx(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple while providing information about element inde...
Definition Tuple.h:522
constexpr TValue tupleAccumulate(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition Tuple.h:587
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.
constexpr unsigned version()
Version of the COMMS library as single numeric value.
Definition version.h:66
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:32
Replacement to some types from standard type_traits.