14#include "comms/util/SizeToType.h"
17#include "comms/details/tag.h"
31template <std::
size_t TLen>
32struct UnsignedValueMaskWrap
34 static const std::uintmax_t Value =
35 static_cast<std::uintmax_t
>(
36 (
static_cast<std::uintmax_t
>(1U) << (TLen * std::numeric_limits<std::uint8_t>::digits)) - 1U);
40struct UnsignedValueMaskWrap<sizeof(
std::uintmax_t)>
42 static const std::uintmax_t Value = std::numeric_limits<std::uintmax_t>::max();
49template <std::
size_t TLen,
bool TSignExtend,
typename TBase>
52 using BaseImpl = TBase;
53 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
56 using ValueType =
typename BaseImpl::ValueType;
58 static_assert(TLen <=
sizeof(BaseSerialisedType),
59 "The provided length limit is too big");
61 using SerialisedType =
63 (TLen <
sizeof(BaseSerialisedType))
65 typename comms::util::SizeToType<TLen, std::is_signed<BaseSerialisedType>::value>::Type,
69 using Endian =
typename BaseImpl::Endian;
80 FixedLength& operator=(
const FixedLength&) =
default;
83 static constexpr std::size_t length()
88 static constexpr std::size_t minLength()
93 static constexpr std::size_t maxLength()
98 static constexpr SerialisedType toSerialised(ValueType val)
100 return adjustToSerialised(BaseImpl::toSerialised(val), ConversionTag<>());
103 static constexpr ValueType fromSerialised(SerialisedType val)
105 return BaseImpl::fromSerialised(adjustFromSerialised(val, ConversionTag<>()));
108 template <
typename TIter>
111 if (size < length()) {
119 template <
typename TIter>
120 void readNoStatus(TIter& iter)
122 auto serialisedValue =
123 comms::util::readData<SerialisedType, Length>(iter,
Endian());
124 BaseImpl::setValue(fromSerialised(serialisedValue));
127 template <
typename TIter>
130 if (size < length()) {
138 template <
typename TIter>
139 void writeNoStatus(TIter& iter)
const
141 BaseImpl::template writeData<Length>(toSerialised(BaseImpl::getValue()), iter);
146 template <
typename... TParams>
147 using JustCastTag = comms::details::tag::Tag1<>;
149 template <
typename... TParams>
150 using SignExtendTag = comms::details::tag::Tag2<>;
152 template <
typename... TParams>
153 using UnsignedTag = comms::details::tag::Tag3<>;
155 template <
typename... TParams>
156 using SignedTag = comms::details::tag::Tag4<>;
158 template <
typename...>
159 using ConversionTag =
160 typename comms::util::LazyShallowConditional<
161 (TLen <
sizeof(SerialisedType))
167 template <
typename...>
169 typename comms::util::LazyShallowConditional<
170 std::is_signed<SerialisedType>::value && TSignExtend
176 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
178 template <
typename... TParams>
179 static constexpr SerialisedType adjustToSerialised(BaseSerialisedType val, JustCastTag<TParams...>)
181 return static_cast<SerialisedType
>(val);
184 template <
typename... TParams>
185 static SerialisedType adjustToSerialised(BaseSerialisedType val, SignExtendTag<TParams...>)
188 static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask;
190 return signExtUnsignedSerialised(valueTmp, HasSignTag<>());
193 template <
typename... TParams>
194 static constexpr BaseSerialisedType adjustFromSerialised(SerialisedType val, JustCastTag<TParams...>)
196 return castToBaseSerializedType(val, HasSignTag<>());
199 template <
typename... TParams>
200 static BaseSerialisedType adjustFromSerialised(SerialisedType val, SignExtendTag<TParams...>)
202 auto valueTmp =
static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask;
203 return castToBaseSerializedType(signExtUnsignedSerialised(valueTmp, HasSignTag<>()), HasSignTag<>());
206 template <
typename... TParams>
207 static constexpr SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val, UnsignedTag<TParams...>)
209 return static_cast<SerialisedType
>(val);
212 template <
typename... TParams>
213 static SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val, SignedTag<TParams...>)
215 static const UnsignedSerialisedType SignExtMask = ~(UnsignedValueMask);
216 static const UnsignedSerialisedType SignMask =
217 static_cast<UnsignedSerialisedType
>(1U) << (BitLength - 1);
219 if ((val & SignMask) != 0) {
222 return static_cast<SerialisedType
>(val);
225 template <
typename... TParams>
226 static constexpr BaseSerialisedType castToBaseSerializedType(SerialisedType val, UnsignedTag<TParams...>)
228 return static_cast<BaseSerialisedType
>(
static_cast<UnsignedSerialisedType
>(val));
231 template <
typename... TParams>
232 static constexpr BaseSerialisedType castToBaseSerializedType(SerialisedType val, SignedTag<TParams...>)
234 return static_cast<BaseSerialisedType
>(val);
237 static const std::size_t Length = TLen;
238 static const std::size_t BitsInByte = std::numeric_limits<std::uint8_t>::digits;
239 static const std::size_t BitLength = Length * BitsInByte;
241 static const UnsignedSerialisedType UnsignedValueMask =
242 static_cast<UnsignedSerialisedType
>(details::UnsignedValueMaskWrap<Length>::Value);
244 static_assert(0 < Length,
"Length is expected to be greater than 0");
This file contains classes required for generic custom assertion functionality.
This file contain definition of error statuses used by comms module.
comms::option::def::FixedLength< TLen, TSignExtend > FixedLength
Same as comms::option::def::FixedLength.
Definition options.h:1488
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1438
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.
Replacement to std::conditional.
Definition type_traits.h:28
Replacement to some types from standard type_traits.