COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
FieldCastHelper.h
1//
2// Copyright 2015 - 2024 (C). Alex Robenko. All rights reserved.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8#pragma once
9
10#include <cstdint>
11#include <iterator>
12#include <type_traits>
13
14#include "comms/ErrorStatus.h"
16#include "comms/details/tag.h"
17
18namespace comms
19{
20
21namespace details
22{
23
24template <typename...>
25class FieldCastHelper
26{
27public:
28 template <typename TFieldTo, typename TFieldFrom>
29 static TFieldTo cast(const TFieldFrom& field)
30 {
31 return castInternal<TFieldTo>(field, Tag<TFieldFrom, TFieldTo>());
32 }
33
34private:
35
36 template <typename... TParams>
37 using StaticCastTag = comms::details::tag::Tag1<>;
38
39 template <typename... TParams>
40 using WriteReadTag = comms::details::tag::Tag2<>;
41
42 template <typename TFieldFrom, typename TFieldTo>
43 using Convertible =
44 std::is_convertible<typename TFieldFrom::ValueType, typename TFieldTo::ValueType>;
45
46 template <typename TField>
47 using IsIntegral =
48 std::integral_constant<
49 bool,
50 std::is_enum<typename TField::ValueType>::value ||
51 std::is_integral<typename TField::ValueType>::value
52 >;
53
54 template <typename TFieldFrom, typename TFieldTo>
55 using UseStaticCast =
56 std::integral_constant<
57 bool,
58 Convertible<TFieldFrom, TFieldTo>::value ||
59 (IsIntegral<TFieldFrom>::value && IsIntegral<TFieldTo>::value)
60 >;
61
62 template <typename TFieldFrom, typename TFieldTo>
63 using Tag =
64 typename comms::util::LazyShallowConditional<
65 UseStaticCast<TFieldFrom, TFieldTo>::value
66 >::template Type<
67 StaticCastTag,
68 WriteReadTag
69 >;
70
71 template <typename TFieldTo, typename TFieldFrom, typename... TParams>
72 static TFieldTo castInternal(const TFieldFrom& field, StaticCastTag<TParams...>)
73 {
74 TFieldTo result;
75 result.value() = static_cast<typename TFieldTo::ValueType>(field.value());
76 return result;
77 }
78
79 template <typename TFieldTo, typename TFieldFrom, typename... TParams>
80 static TFieldTo castInternal(const TFieldFrom& field, WriteReadTag<TParams...>)
81 {
82 static_assert(TFieldFrom::minLength() <= TFieldTo::maxLength(), "Casting between specified fields will fail .");
83
84 static const auto MaxBufSize = TFieldFrom::maxLength();
85 std::uint8_t buf[MaxBufSize] = {0};
86 auto* writeIter = &buf[0];
87 auto es = field.write(writeIter, MaxBufSize);
90 return TFieldTo();
91 }
92
93 auto len = static_cast<std::size_t>(std::distance(&buf[0], writeIter));
94 COMMS_ASSERT(len <= MaxBufSize);
95
96 TFieldTo result;
97 const auto* readIter = &buf[0];
98 es = result.read(readIter, len);
99 static_cast<void>(es);
101 return result;
102 }
103};
104
105
106} // namespace details
107
108} // namespace comms
109
110
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
This file contain definition of error statuses used by comms module.
Main namespace for all classes / functions of COMMS library.
@ Success
Used to indicate successful outcome of the operation.
Replacement to some types from standard type_traits.