14#include "comms/details/tag.h"
16#include "comms/util/SizeToType.h"
36template <
typename TBase>
37class AvailableLength :
public TBase
39 using BaseImpl = TBase;
40 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
44 using ValueType =
typename BaseImpl::ValueType;
45 using SerialisedType =
typename BaseImpl::SerialisedType;
47 using Endian =
typename BaseImpl::Endian;
49 AvailableLength() =
default;
51 explicit AvailableLength(
const ValueType& val)
56 explicit AvailableLength(ValueType&& val)
57 : BaseImpl(
std::move(val))
61 AvailableLength(
const AvailableLength&) =
default;
62 AvailableLength(AvailableLength&&) =
default;
63 AvailableLength& operator=(
const AvailableLength&) =
default;
64 AvailableLength& operator=(AvailableLength&&) =
default;
66 void setForcedLength(
int len)
71 int getForcedLength()
const
73 return m_forcedLength;
76 std::size_t length()
const
78 if (m_forcedLength == 0) {
79 return BaseImpl::length();
82 if (0 < m_forcedLength) {
83 return std::min(BaseImpl::length(),
static_cast<std::size_t
>(m_forcedLength));
86 auto serValue = toSerialised(BaseImpl::getValue());
87 for (std::size_t len = 1U; len <
sizeof(SerialisedType); ++len) {
88 if (fitsLength(serValue, len)) {
93 return BaseImpl::length();
96 static constexpr std::size_t minLength()
101 static constexpr std::size_t maxLength()
103 return BaseImpl::maxLength();
106 static constexpr SerialisedType toSerialised(ValueType val)
108 return static_cast<SerialisedType
>(BaseImpl::toSerialised(val));
111 static constexpr ValueType fromSerialised(SerialisedType val)
113 return BaseImpl::fromSerialised(
static_cast<BaseSerialisedType
>(val));
116 template <
typename TIter>
123 auto fromIter = iter;
124 auto unsignedSerialized = util::readData<UnsignedSerialisedType>(iter, std::min(size, BaseImpl::maxLength()),
Endian());
125 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
126 BaseImpl::setValue(fromSerialised(signExtUnsignedSerialised(unsignedSerialized, len, HasSignTag())));
130 static constexpr bool hasReadNoStatus()
135 template <
typename TIter>
136 void readNoStatus(TIter& iter) =
delete;
138 template <
typename TIter>
141 if (m_forcedLength == 0) {
142 return BaseImpl::write(iter, size);
145 if (!BaseImpl::canWrite()) {
149 auto fieldLen = length();
150 if (size < fieldLen) {
154 auto serValue = toSerialised(BaseImpl::getValue());
155 if (0 < m_forcedLength) {
161 std::size_t len = 1U;
162 for (; len <
sizeof(serValue); ++len) {
163 if (!fitsLength(serValue, len)) {
171 return BaseImpl::write(iter, size);
174 static constexpr bool hasWriteNoStatus()
179 template <
typename TIter>
180 void writeNoStatus(TIter& iter)
const =
delete;
183 template <
typename... TParams>
184 using UnsignedTag = comms::details::tag::Tag1<>;
186 template <
typename... TParams>
187 using SignedTag = comms::details::tag::Tag2<>;
190 typename comms::util::LazyShallowConditional<
191 std::is_signed<SerialisedType>::value
197 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
199 template <
typename... TParams>
200 static constexpr SerialisedType signExtUnsignedSerialised(
201 UnsignedSerialisedType val,
203 UnsignedTag<TParams...>)
205 return static_cast<SerialisedType
>(val);
208 template <
typename... TParams>
209 static SerialisedType signExtUnsignedSerialised(
210 UnsignedSerialisedType val,
211 std::size_t bytesCount,
212 SignedTag<TParams...>)
214 UnsignedSerialisedType signBitMask =
215 static_cast<UnsignedSerialisedType
>(1U) << ((bytesCount * BitsInByte) - (bytesCount + 1));
217 if ((val & signBitMask) == 0U) {
218 return static_cast<SerialisedType
>(val);
221 UnsignedSerialisedType signExtMask =
222 static_cast<UnsignedSerialisedType
>(~(signBitMask - 1));
225 return static_cast<SerialisedType
>(val);
228 template <
typename... TParams>
229 static SerialisedType getMinLimitedValue(std::size_t len, UnsignedTag<TParams...>)
231 static_cast<void>(len);
232 return static_cast<SerialisedType
>(0);
235 template <
typename... TParams>
236 static SerialisedType getMinLimitedValue(std::size_t len, SignedTag<TParams...>)
240 ((
static_cast<UnsignedSerialisedType
>(1U) << ((len * BitsInByte) - 1)) - 1U);
242 return static_cast<SerialisedType
>(~static_cast<UnsignedSerialisedType>(mask));
245 template <
typename... TParams>
246 static SerialisedType getMaxLimitedValue(std::size_t len, UnsignedTag<TParams...>)
250 ((
static_cast<UnsignedSerialisedType
>(1U) << (len * BitsInByte)) - 1U);
251 return static_cast<SerialisedType
>(value);
254 template <
typename... TParams>
255 static SerialisedType getMaxLimitedValue(std::size_t len, SignedTag<TParams...>)
259 ((
static_cast<UnsignedSerialisedType
>(1U) << ((len * BitsInByte) - 1)) - 1U);
260 return static_cast<SerialisedType
>(value);
263 static bool fitsLength(SerialisedType val, std::size_t len)
265 if (
sizeof(val) <= len) {
269 auto minValue = getMinLimitedValue(len, HasSignTag());
270 auto maxValue = getMaxLimitedValue(len, HasSignTag());
271 return ((minValue <= val) && (val <= maxValue));
274 static const std::size_t BitsInByte =
275 std::numeric_limits<std::uint8_t>::digits;
277 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:1473
void writeData(T value, TIter &iter, const traits::endian::Big &endian)
Same as writeBig<T, TIter>()
Definition access.h:707
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.
@ InvalidMsgData
Used to indicate that a message has invalid data.
Replacement to some types from standard type_traits.