13#include "comms/details/tag.h"
15#include "comms/util/SizeToType.h"
16#include "comms/util/BitSizeToByteSize.h"
31template <std::
size_t TLen,
bool TSignExtend,
typename TBase>
34 using BaseImpl = TBase;
35 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
36 using BaseUnsignedSerialisedType =
typename std::make_unsigned<BaseSerialisedType>::type;
38 static const std::size_t BitLength = TLen;
39 static const std::size_t Length =
40 comms::util::BitSizeToByteSize<BitLength>::Value;
42 static_assert(0 < BitLength,
"Bit length is expected to be greater than 0");
43 static_assert(Length <=
sizeof(BaseSerialisedType),
44 "The provided length limit is too big");
48 using ValueType =
typename BaseImpl::ValueType;
50 using SerialisedType =
52 (Length <
sizeof(BaseSerialisedType))
54 typename comms::util::SizeToType<Length, std::is_signed<BaseSerialisedType>::value>::Type,
58 using Endian =
typename BaseImpl::Endian;
72 static constexpr std::size_t length()
77 static constexpr std::size_t minLength()
82 static constexpr std::size_t maxLength()
87 static constexpr SerialisedType toSerialised(ValueType val)
89 return adjustToSerialised(BaseImpl::toSerialised(val), HasSignTag<>());
92 static constexpr ValueType fromSerialised(SerialisedType val)
94 return BaseImpl::fromSerialised(adjustFromSerialised(val, HasSignTag<>()));
97 template <
typename TIter>
100 if (size < length()) {
108 template <
typename TIter>
109 void readNoStatus(TIter& iter)
111 auto serialisedValue =
112 comms::util::readData<SerialisedType, Length>(iter,
Endian());
113 BaseImpl::setValue(fromSerialised(serialisedValue));
116 template <
typename TIter>
119 if (size < length()) {
127 template <
typename TIter>
128 void writeNoStatus(TIter& iter)
const
130 BaseImpl::template writeData<Length>(toSerialised(BaseImpl::getValue()), iter);
134 template <
typename... TParams>
135 using UnsignedTag = comms::details::tag::Tag1<>;
137 template <
typename... TParams>
138 using SignedTag = comms::details::tag::Tag2<>;
140 template <
typename... TParams>
141 using NoSignExtTag = comms::details::tag::Tag3<>;
143 template <
typename... TParams>
144 using MustSignExtTag = comms::details::tag::Tag4<>;
146 template <
typename...>
148 typename comms::util::LazyShallowConditional<
149 TSignExtend && std::is_signed<SerialisedType>::value
155 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
157 template <
typename... TParams>
158 static SerialisedType adjustToSerialised(BaseSerialisedType val, UnsignedTag<TParams...>)
160 return static_cast<SerialisedType
>(
static_cast<BaseUnsignedSerialisedType
>(val) & UnsignedValueMask);
163 template <
typename... TParams>
164 static SerialisedType adjustToSerialised(BaseSerialisedType val, SignedTag<TParams...>)
167 static_cast<UnsignedSerialisedType
>(
168 static_cast<BaseUnsignedSerialisedType
>(val) & UnsignedValueMask);
170 return signExtUnsignedSerialised(valueTmp);
173 template <
typename... TParams>
174 static BaseSerialisedType adjustFromSerialised(SerialisedType val, UnsignedTag<TParams...>)
176 return static_cast<BaseSerialisedType
>(
static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask);
179 template <
typename... TParams>
180 static BaseSerialisedType adjustFromSerialised(SerialisedType val, SignedTag<TParams...>)
183 static_cast<UnsignedSerialisedType
>(
184 static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask);
186 static_cast<BaseSerialisedType
>(
187 signExtUnsignedSerialised(valueTmp));
190 static SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val)
193 typename comms::util::LazyShallowConditional<
194 BitLength < static_cast<std::size_t>(std::numeric_limits<UnsignedSerialisedType>::digits)
199 return signExtUnsignedSerialisedInternal(val, SignExtTag());
202 template <
typename... TParams>
203 static SerialisedType signExtUnsignedSerialisedInternal(UnsignedSerialisedType val, MustSignExtTag<TParams...>)
206 BitLength < std::numeric_limits<UnsignedSerialisedType>::digits,
207 "BitLength is expected to be less than number of bits in the value type");
209 static const auto SignExtMask =
210 static_cast<UnsignedSerialisedType
>(
211 ~((
static_cast<UnsignedSerialisedType
>(1U) << BitLength) - 1));
213 static const auto SignMask =
214 static_cast<UnsignedSerialisedType
>(
215 static_cast<UnsignedSerialisedType
>(1U) << (BitLength - 1));
217 if ((val & SignMask) != 0) {
220 return static_cast<SerialisedType
>(val);
223 template <
typename... TParams>
224 static SerialisedType signExtUnsignedSerialisedInternal(UnsignedSerialisedType val, NoSignExtTag<TParams...>)
226 return static_cast<SerialisedType
>(val);
230 static const UnsignedSerialisedType UnsignedValueMask =
231 (
static_cast<UnsignedSerialisedType
>(1U) << BitLength) - 1;
This file contains classes required for generic custom assertion functionality.
This file contain definition of error statuses used by comms module.
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1473
comms::option::def::FixedBitLength< TLen, TSignExtend > FixedBitLength
Same as comms::option::def::FixedBitLength.
Definition options.h:1542
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.
Replacement to std::conditional.
Definition type_traits.h:32
Replacement to some types from standard type_traits.