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