15#include "comms/util/SizeToType.h"
19#include "comms/details/tag.h"
31template <
typename TBase>
32class AvailableLength :
public TBase
34 using BaseImpl = TBase;
35 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
39 using ValueType =
typename BaseImpl::ValueType;
40 using SerialisedType =
typename BaseImpl::SerialisedType;
42 using Endian =
typename BaseImpl::Endian;
44 AvailableLength() =
default;
46 explicit AvailableLength(
const ValueType& val)
51 explicit AvailableLength(ValueType&& val)
52 : BaseImpl(
std::move(val))
56 AvailableLength(
const AvailableLength&) =
default;
57 AvailableLength(AvailableLength&&) =
default;
58 AvailableLength& operator=(
const AvailableLength&) =
default;
59 AvailableLength& operator=(AvailableLength&&) =
default;
61 void setForcedLength(
int len)
66 int getForcedLength()
const
68 return m_forcedLength;
71 std::size_t length()
const
73 if (m_forcedLength == 0) {
74 return BaseImpl::length();
77 if (0 < m_forcedLength) {
78 return std::min(BaseImpl::length(),
static_cast<std::size_t
>(m_forcedLength));
81 auto serValue = toSerialised(BaseImpl::getValue());
82 for (std::size_t len = 1U; len <
sizeof(SerialisedType); ++len) {
83 if (fitsLength(serValue, len)) {
88 return BaseImpl::length();
91 static constexpr std::size_t minLength()
96 static constexpr std::size_t maxLength()
98 return BaseImpl::maxLength();
101 static constexpr SerialisedType toSerialised(ValueType val)
103 return static_cast<SerialisedType
>(BaseImpl::toSerialised(val));
106 static constexpr ValueType fromSerialised(SerialisedType val)
108 return BaseImpl::fromSerialised(
static_cast<BaseSerialisedType
>(val));
111 template <
typename TIter>
118 auto fromIter = iter;
119 auto unsignedSerialized = util::readData<UnsignedSerialisedType>(iter, std::min(size, BaseImpl::maxLength()),
Endian());
120 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
121 BaseImpl::setValue(fromSerialised(signExtUnsignedSerialised(unsignedSerialized, len, HasSignTag())));
125 static constexpr bool hasReadNoStatus()
130 template <
typename TIter>
131 void readNoStatus(TIter& iter) =
delete;
133 template <
typename TIter>
136 if (m_forcedLength == 0) {
137 return BaseImpl::write(iter, size);
140 if (!BaseImpl::canWrite()) {
144 auto fieldLen = length();
145 if (size < fieldLen) {
149 auto serValue = toSerialised(BaseImpl::getValue());
150 if (0 < m_forcedLength) {
156 std::size_t len = 1U;
157 for (; len <
sizeof(serValue); ++len) {
158 if (!fitsLength(serValue, len)) {
166 return BaseImpl::write(iter, size);
169 static constexpr bool hasWriteNoStatus()
174 template <
typename TIter>
175 void writeNoStatus(TIter& iter)
const =
delete;
178 template <
typename... TParams>
179 using UnsignedTag = comms::details::tag::Tag1<>;
181 template <
typename... TParams>
182 using SignedTag = comms::details::tag::Tag2<>;
185 typename comms::util::LazyShallowConditional<
186 std::is_signed<SerialisedType>::value
192 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
194 template <
typename... TParams>
195 static constexpr SerialisedType signExtUnsignedSerialised(
196 UnsignedSerialisedType val,
198 UnsignedTag<TParams...>)
200 return static_cast<SerialisedType
>(val);
203 template <
typename... TParams>
204 static SerialisedType signExtUnsignedSerialised(
205 UnsignedSerialisedType val,
206 std::size_t bytesCount,
207 SignedTag<TParams...>)
209 UnsignedSerialisedType signBitMask =
210 static_cast<UnsignedSerialisedType
>(1U) << ((bytesCount * BitsInByte) - (bytesCount + 1));
212 if ((val & signBitMask) == 0U) {
213 return static_cast<SerialisedType
>(val);
216 UnsignedSerialisedType signExtMask =
217 static_cast<UnsignedSerialisedType
>(~(signBitMask - 1));
220 return static_cast<SerialisedType
>(val);
224 template <
typename... TParams>
225 static SerialisedType getMinLimitedValue(std::size_t len, UnsignedTag<TParams...>)
227 static_cast<void>(len);
228 return static_cast<SerialisedType
>(0);
231 template <
typename... TParams>
232 static SerialisedType getMinLimitedValue(std::size_t len, SignedTag<TParams...>)
236 ((
static_cast<UnsignedSerialisedType
>(1U) << ((len * BitsInByte) - 1)) - 1U);
238 return static_cast<SerialisedType
>(~static_cast<UnsignedSerialisedType>(mask));
241 template <
typename... TParams>
242 static SerialisedType getMaxLimitedValue(std::size_t len, UnsignedTag<TParams...>)
246 ((
static_cast<UnsignedSerialisedType
>(1U) << (len * BitsInByte)) - 1U);
247 return static_cast<SerialisedType
>(value);
250 template <
typename... TParams>
251 static SerialisedType getMaxLimitedValue(std::size_t len, SignedTag<TParams...>)
255 ((
static_cast<UnsignedSerialisedType
>(1U) << ((len * BitsInByte) - 1)) - 1U);
256 return static_cast<SerialisedType
>(value);
260 static bool fitsLength(SerialisedType val, std::size_t len)
262 if (
sizeof(val) <= len) {
266 auto minValue = getMinLimitedValue(len, HasSignTag());
267 auto maxValue = getMaxLimitedValue(len, HasSignTag());
268 return ((minValue <= val) && (val <= maxValue));
271 static const std::size_t BitsInByte =
272 std::numeric_limits<std::uint8_t>::digits;
275 int m_forcedLength = -1;
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.
Contains functions for raw data access / (de)serialization.
Contains definition of various casts.
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1438
void writeData(T value, TIter &iter, const traits::endian::Big &endian)
Same as writeBig<T, TIter>()
Definition access.h:706
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.