11#include "comms/details/tag.h"
13#include "comms/util/SizeToType.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();
47template <std::
size_t TLen,
bool TSignExtend,
typename TBase>
50 using BaseImpl = TBase;
51 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
54 using ValueType =
typename BaseImpl::ValueType;
56 static_assert(TLen <=
sizeof(BaseSerialisedType),
57 "The provided length limit is too big");
59 using SerialisedType =
61 (TLen <
sizeof(BaseSerialisedType))
63 typename comms::util::SizeToType<TLen, std::is_signed<BaseSerialisedType>::value>::Type,
67 using Endian =
typename BaseImpl::Endian;
78 FixedLength& operator=(
const FixedLength&) =
default;
81 static constexpr std::size_t length()
86 static constexpr std::size_t minLength()
91 static constexpr std::size_t maxLength()
96 static constexpr SerialisedType toSerialised(ValueType val)
98 return adjustToSerialised(BaseImpl::toSerialised(val), ConversionTag<>());
101 static constexpr ValueType fromSerialised(SerialisedType val)
103 return BaseImpl::fromSerialised(adjustFromSerialised(val, ConversionTag<>()));
106 template <
typename TIter>
109 if (size < length()) {
117 template <
typename TIter>
118 void readNoStatus(TIter& iter)
120 auto serialisedValue =
121 comms::util::readData<SerialisedType, Length>(iter,
Endian());
122 BaseImpl::setValue(fromSerialised(serialisedValue));
125 template <
typename TIter>
128 if (size < length()) {
136 template <
typename TIter>
137 void writeNoStatus(TIter& iter)
const
139 BaseImpl::template writeData<Length>(toSerialised(BaseImpl::getValue()), iter);
144 template <
typename... TParams>
145 using JustCastTag = comms::details::tag::Tag1<>;
147 template <
typename... TParams>
148 using SignExtendTag = comms::details::tag::Tag2<>;
150 template <
typename... TParams>
151 using UnsignedTag = comms::details::tag::Tag3<>;
153 template <
typename... TParams>
154 using SignedTag = comms::details::tag::Tag4<>;
156 template <
typename...>
157 using ConversionTag =
158 typename comms::util::LazyShallowConditional<
159 (TLen <
sizeof(SerialisedType))
165 template <
typename...>
167 typename comms::util::LazyShallowConditional<
168 std::is_signed<SerialisedType>::value && TSignExtend
174 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
176 template <
typename... TParams>
177 static constexpr SerialisedType adjustToSerialised(BaseSerialisedType val, JustCastTag<TParams...>)
179 return static_cast<SerialisedType
>(val);
182 template <
typename... TParams>
183 static SerialisedType adjustToSerialised(BaseSerialisedType val, SignExtendTag<TParams...>)
186 static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask;
188 return signExtUnsignedSerialised(valueTmp, HasSignTag<>());
191 template <
typename... TParams>
192 static constexpr BaseSerialisedType adjustFromSerialised(SerialisedType val, JustCastTag<TParams...>)
194 return castToBaseSerializedType(val, HasSignTag<>());
197 template <
typename... TParams>
198 static BaseSerialisedType adjustFromSerialised(SerialisedType val, SignExtendTag<TParams...>)
200 auto valueTmp =
static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask;
201 return castToBaseSerializedType(signExtUnsignedSerialised(valueTmp, HasSignTag<>()), HasSignTag<>());
204 template <
typename... TParams>
205 static constexpr SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val, UnsignedTag<TParams...>)
207 return static_cast<SerialisedType
>(val);
210 template <
typename... TParams>
211 static SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val, SignedTag<TParams...>)
213 static const UnsignedSerialisedType SignExtMask = ~(UnsignedValueMask);
214 static const UnsignedSerialisedType SignMask =
215 static_cast<UnsignedSerialisedType
>(1U) << (BitLength - 1);
217 if ((val & SignMask) != 0) {
220 return static_cast<SerialisedType
>(val);
223 template <
typename... TParams>
224 static constexpr BaseSerialisedType castToBaseSerializedType(SerialisedType val, UnsignedTag<TParams...>)
226 return static_cast<BaseSerialisedType
>(
static_cast<UnsignedSerialisedType
>(val));
229 template <
typename... TParams>
230 static constexpr BaseSerialisedType castToBaseSerializedType(SerialisedType val, SignedTag<TParams...>)
232 return static_cast<BaseSerialisedType
>(val);
235 static const std::size_t Length = TLen;
236 static const std::size_t BitsInByte = std::numeric_limits<std::uint8_t>::digits;
237 static const std::size_t BitLength = Length * BitsInByte;
239 static const UnsignedSerialisedType UnsignedValueMask =
240 static_cast<UnsignedSerialisedType
>(details::UnsignedValueMaskWrap<Length>::Value);
242 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:1535
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1471
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:29
Replacement to some types from standard type_traits.