14#include "comms/util/SizeToType.h"
15#include "comms/util/BitSizeToByteSize.h"
18#include "comms/details/tag.h"
29template <std::
size_t TLen,
bool TSignExtend,
typename TBase>
32 using BaseImpl = TBase;
33 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
34 using BaseUnsignedSerialisedType =
typename std::make_unsigned<BaseSerialisedType>::type;
36 static const std::size_t BitLength = TLen;
37 static const std::size_t Length =
38 comms::util::BitSizeToByteSize<BitLength>::Value;
40 static_assert(0 < BitLength,
"Bit length is expected to be greater than 0");
41 static_assert(Length <=
sizeof(BaseSerialisedType),
42 "The provided length limit is too big");
46 using ValueType =
typename BaseImpl::ValueType;
48 using SerialisedType =
50 (Length <
sizeof(BaseSerialisedType))
52 typename comms::util::SizeToType<Length, std::is_signed<BaseSerialisedType>::value>::Type,
56 using Endian =
typename BaseImpl::Endian;
70 static constexpr std::size_t length()
75 static constexpr std::size_t minLength()
80 static constexpr std::size_t maxLength()
85 static constexpr SerialisedType toSerialised(ValueType val)
87 return adjustToSerialised(BaseImpl::toSerialised(val), HasSignTag<>());
90 static constexpr ValueType fromSerialised(SerialisedType val)
92 return BaseImpl::fromSerialised(adjustFromSerialised(val, HasSignTag<>()));
95 template <
typename TIter>
98 if (size < length()) {
106 template <
typename TIter>
107 void readNoStatus(TIter& iter)
109 auto serialisedValue =
110 comms::util::readData<SerialisedType, Length>(iter,
Endian());
111 BaseImpl::setValue(fromSerialised(serialisedValue));
114 template <
typename TIter>
117 if (size < length()) {
125 template <
typename TIter>
126 void writeNoStatus(TIter& iter)
const
128 BaseImpl::template writeData<Length>(toSerialised(BaseImpl::getValue()), iter);
132 template <
typename... TParams>
133 using UnsignedTag = comms::details::tag::Tag1<>;
135 template <
typename... TParams>
136 using SignedTag = comms::details::tag::Tag2<>;
138 template <
typename... TParams>
139 using NoSignExtTag = comms::details::tag::Tag3<>;
141 template <
typename... TParams>
142 using MustSignExtTag = comms::details::tag::Tag4<>;
144 template <
typename...>
146 typename comms::util::LazyShallowConditional<
147 TSignExtend && std::is_signed<SerialisedType>::value
153 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
155 template <
typename... TParams>
156 static SerialisedType adjustToSerialised(BaseSerialisedType val, UnsignedTag<TParams...>)
158 return static_cast<SerialisedType
>(
static_cast<BaseUnsignedSerialisedType
>(val) & UnsignedValueMask);
161 template <
typename... TParams>
162 static SerialisedType adjustToSerialised(BaseSerialisedType val, SignedTag<TParams...>)
165 static_cast<UnsignedSerialisedType
>(
166 static_cast<BaseUnsignedSerialisedType
>(val) & UnsignedValueMask);
168 return signExtUnsignedSerialised(valueTmp);
171 template <
typename... TParams>
172 static BaseSerialisedType adjustFromSerialised(SerialisedType val, UnsignedTag<TParams...>)
174 return static_cast<BaseSerialisedType
>(
static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask);
177 template <
typename... TParams>
178 static BaseSerialisedType adjustFromSerialised(SerialisedType val, SignedTag<TParams...>)
181 static_cast<UnsignedSerialisedType
>(
182 static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask);
184 static_cast<BaseSerialisedType
>(
185 signExtUnsignedSerialised(valueTmp));
188 static SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val)
191 typename comms::util::LazyShallowConditional<
192 BitLength < static_cast<std::size_t>(std::numeric_limits<UnsignedSerialisedType>::digits)
197 return signExtUnsignedSerialisedInternal(val, SignExtTag());
200 template <
typename... TParams>
201 static SerialisedType signExtUnsignedSerialisedInternal(UnsignedSerialisedType val, MustSignExtTag<TParams...>)
204 BitLength < std::numeric_limits<UnsignedSerialisedType>::digits,
205 "BitLength is expected to be less than number of bits in the value type");
207 static const auto SignExtMask =
208 static_cast<UnsignedSerialisedType
>(
209 ~((
static_cast<UnsignedSerialisedType
>(1U) << BitLength) - 1));
211 static const auto SignMask =
212 static_cast<UnsignedSerialisedType
>(
213 static_cast<UnsignedSerialisedType
>(1U) << (BitLength - 1));
215 if ((val & SignMask) != 0) {
218 return static_cast<SerialisedType
>(val);
221 template <
typename... TParams>
222 static SerialisedType signExtUnsignedSerialisedInternal(UnsignedSerialisedType val, NoSignExtTag<TParams...>)
224 return static_cast<SerialisedType
>(val);
228 static const UnsignedSerialisedType UnsignedValueMask =
229 (
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:1438
comms::option::def::FixedBitLength< TLen, TSignExtend > FixedBitLength
Same as comms::option::def::FixedBitLength.
Definition options.h:1492
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.