12#include "comms/details/tag.h"
14#include "comms/util/SizeToType.h"
32template <
typename TBase>
33class AvailableLength :
public TBase
35 using BaseImpl = TBase;
36 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
40 using ValueType =
typename BaseImpl::ValueType;
41 using SerialisedType =
typename BaseImpl::SerialisedType;
43 using Endian =
typename BaseImpl::Endian;
45 AvailableLength() =
default;
47 explicit AvailableLength(
const ValueType& val)
52 explicit AvailableLength(ValueType&& val)
53 : BaseImpl(
std::move(val))
57 AvailableLength(
const AvailableLength&) =
default;
58 AvailableLength(AvailableLength&&) =
default;
59 AvailableLength& operator=(
const AvailableLength&) =
default;
60 AvailableLength& operator=(AvailableLength&&) =
default;
62 void setForcedLength(
int len)
67 int getForcedLength()
const
69 return m_forcedLength;
72 std::size_t length()
const
74 if (m_forcedLength == 0) {
75 return BaseImpl::length();
78 if (0 < m_forcedLength) {
79 return std::min(BaseImpl::length(),
static_cast<std::size_t
>(m_forcedLength));
82 auto serValue = toSerialised(BaseImpl::getValue());
83 for (std::size_t len = 1U; len <
sizeof(SerialisedType); ++len) {
84 if (fitsLength(serValue, len)) {
89 return BaseImpl::length();
92 static constexpr std::size_t minLength()
97 static constexpr std::size_t maxLength()
99 return BaseImpl::maxLength();
102 static constexpr SerialisedType toSerialised(ValueType val)
104 return static_cast<SerialisedType
>(BaseImpl::toSerialised(val));
107 static constexpr ValueType fromSerialised(SerialisedType val)
109 return BaseImpl::fromSerialised(
static_cast<BaseSerialisedType
>(val));
112 template <
typename TIter>
119 auto fromIter = iter;
120 auto unsignedSerialized = util::readData<UnsignedSerialisedType>(iter, std::min(size, BaseImpl::maxLength()),
Endian());
121 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
122 BaseImpl::setValue(fromSerialised(signExtUnsignedSerialised(unsignedSerialized, len, HasSignTag())));
126 static constexpr bool hasReadNoStatus()
131 template <
typename TIter>
132 void readNoStatus(TIter& iter) =
delete;
134 template <
typename TIter>
137 if (m_forcedLength == 0) {
138 return BaseImpl::write(iter, size);
141 if (!BaseImpl::canWrite()) {
145 auto fieldLen = length();
146 if (size < fieldLen) {
150 auto serValue = toSerialised(BaseImpl::getValue());
151 if (0 < m_forcedLength) {
157 std::size_t len = 1U;
158 for (; len <
sizeof(serValue); ++len) {
159 if (!fitsLength(serValue, len)) {
167 return BaseImpl::write(iter, size);
170 static constexpr bool hasWriteNoStatus()
175 template <
typename TIter>
176 void writeNoStatus(TIter& iter)
const =
delete;
179 template <
typename... TParams>
180 using UnsignedTag = comms::details::tag::Tag1<>;
182 template <
typename... TParams>
183 using SignedTag = comms::details::tag::Tag2<>;
186 typename comms::util::LazyShallowConditional<
187 std::is_signed<SerialisedType>::value
193 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
195 template <
typename... TParams>
196 static constexpr SerialisedType signExtUnsignedSerialised(
197 UnsignedSerialisedType val,
199 UnsignedTag<TParams...>)
201 return static_cast<SerialisedType
>(val);
204 template <
typename... TParams>
205 static SerialisedType signExtUnsignedSerialised(
206 UnsignedSerialisedType val,
207 std::size_t bytesCount,
208 SignedTag<TParams...>)
210 UnsignedSerialisedType signBitMask =
211 static_cast<UnsignedSerialisedType
>(1U) << ((bytesCount * BitsInByte) - (bytesCount + 1));
213 if ((val & signBitMask) == 0U) {
214 return static_cast<SerialisedType
>(val);
217 UnsignedSerialisedType signExtMask =
218 static_cast<UnsignedSerialisedType
>(~(signBitMask - 1));
221 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);
259 static bool fitsLength(SerialisedType val, std::size_t len)
261 if (
sizeof(val) <= len) {
265 auto minValue = getMinLimitedValue(len, HasSignTag());
266 auto maxValue = getMaxLimitedValue(len, HasSignTag());
267 return ((minValue <= val) && (val <= maxValue));
270 static const std::size_t BitsInByte =
271 std::numeric_limits<std::uint8_t>::digits;
273 int m_forcedLength = -1;
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:168
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:1471
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.