13#include "comms/details/tag.h"
15#include "comms/util/SizeToType.h"
34template <std::
size_t TLen>
35struct UnsignedValueMaskWrap
37 static const std::uintmax_t Value =
38 static_cast<std::uintmax_t
>(
39 (
static_cast<std::uintmax_t
>(1U) << (TLen * std::numeric_limits<std::uint8_t>::digits)) - 1U);
43struct UnsignedValueMaskWrap<sizeof(
std::uintmax_t)>
45 static const std::uintmax_t Value = std::numeric_limits<std::uintmax_t>::max();
50template <std::
size_t TLen,
bool TSignExtend,
typename TBase>
53 using BaseImpl = TBase;
54 using BaseSerialisedType =
typename BaseImpl::SerialisedType;
57 using ValueType =
typename BaseImpl::ValueType;
59 static_assert(TLen <=
sizeof(BaseSerialisedType),
60 "The provided length limit is too big");
62 using SerialisedType =
64 (TLen <
sizeof(BaseSerialisedType))
66 typename comms::util::SizeToType<TLen, std::is_signed<BaseSerialisedType>::value>::Type,
70 using Endian =
typename BaseImpl::Endian;
81 FixedLength& operator=(
const FixedLength&) =
default;
84 static constexpr std::size_t length()
89 static constexpr std::size_t minLength()
94 static constexpr std::size_t maxLength()
99 static constexpr SerialisedType toSerialised(ValueType val)
101 return adjustToSerialised(BaseImpl::toSerialised(val), ConversionTag<>());
104 static constexpr ValueType fromSerialised(SerialisedType val)
106 return BaseImpl::fromSerialised(adjustFromSerialised(val, ConversionTag<>()));
109 template <
typename TIter>
112 if (size < length()) {
120 template <
typename TIter>
121 void readNoStatus(TIter& iter)
123 auto serialisedValue =
124 comms::util::readData<SerialisedType, Length>(iter,
Endian());
125 BaseImpl::setValue(fromSerialised(serialisedValue));
128 template <
typename TIter>
131 if (size < length()) {
139 template <
typename TIter>
140 void writeNoStatus(TIter& iter)
const
142 BaseImpl::template writeData<Length>(toSerialised(BaseImpl::getValue()), iter);
147 template <
typename... TParams>
148 using JustCastTag = comms::details::tag::Tag1<>;
150 template <
typename... TParams>
151 using SignExtendTag = comms::details::tag::Tag2<>;
153 template <
typename... TParams>
154 using UnsignedTag = comms::details::tag::Tag3<>;
156 template <
typename... TParams>
157 using SignedTag = comms::details::tag::Tag4<>;
159 template <
typename...>
160 using ConversionTag =
161 typename comms::util::LazyShallowConditional<
162 (TLen <
sizeof(SerialisedType))
168 template <
typename...>
170 typename comms::util::LazyShallowConditional<
171 std::is_signed<SerialisedType>::value && TSignExtend
177 using UnsignedSerialisedType =
typename std::make_unsigned<SerialisedType>::type;
179 template <
typename... TParams>
180 static constexpr SerialisedType adjustToSerialised(BaseSerialisedType val, JustCastTag<TParams...>)
182 return static_cast<SerialisedType
>(val);
185 template <
typename... TParams>
186 static SerialisedType adjustToSerialised(BaseSerialisedType val, SignExtendTag<TParams...>)
189 static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask;
191 return signExtUnsignedSerialised(valueTmp, HasSignTag<>());
194 template <
typename... TParams>
195 static constexpr BaseSerialisedType adjustFromSerialised(SerialisedType val, JustCastTag<TParams...>)
197 return castToBaseSerializedType(val, HasSignTag<>());
200 template <
typename... TParams>
201 static BaseSerialisedType adjustFromSerialised(SerialisedType val, SignExtendTag<TParams...>)
203 auto valueTmp =
static_cast<UnsignedSerialisedType
>(val) & UnsignedValueMask;
204 return castToBaseSerializedType(signExtUnsignedSerialised(valueTmp, HasSignTag<>()), HasSignTag<>());
207 template <
typename... TParams>
208 static constexpr SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val, UnsignedTag<TParams...>)
210 return static_cast<SerialisedType
>(val);
213 template <
typename... TParams>
214 static SerialisedType signExtUnsignedSerialised(UnsignedSerialisedType val, SignedTag<TParams...>)
216 static const UnsignedSerialisedType SignExtMask = ~(UnsignedValueMask);
217 static const UnsignedSerialisedType SignMask =
218 static_cast<UnsignedSerialisedType
>(1U) << (BitLength - 1);
220 if ((val & SignMask) != 0) {
223 return static_cast<SerialisedType
>(val);
226 template <
typename... TParams>
227 static constexpr BaseSerialisedType castToBaseSerializedType(SerialisedType val, UnsignedTag<TParams...>)
229 return static_cast<BaseSerialisedType
>(
static_cast<UnsignedSerialisedType
>(val));
232 template <
typename... TParams>
233 static constexpr BaseSerialisedType castToBaseSerializedType(SerialisedType val, SignedTag<TParams...>)
235 return static_cast<BaseSerialisedType
>(val);
238 static const std::size_t Length = TLen;
239 static const std::size_t BitsInByte = std::numeric_limits<std::uint8_t>::digits;
240 static const std::size_t BitLength = Length * BitsInByte;
242 static const UnsignedSerialisedType UnsignedValueMask =
243 static_cast<UnsignedSerialisedType
>(details::UnsignedValueMaskWrap<Length>::Value);
245 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:1537
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1473
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.