Sen API
Sen Libraries
Loading...
Searching...
No Matches
variant_traits.h
Go to the documentation of this file.
1// === variant_traits.h ================================================================================================
2// Sen Infrastructure
3// Released under the Apache License v2.0 (SPDX-License-Identifier Apache-2.0).
4// See the LICENSE.txt file for more information.
5// © Airbus SAS, Airbus Helicopters, and Airbus Defence and Space SAU/GmbH/SAS.
6// =====================================================================================================================
7
8#ifndef SEN_CORE_META_VARIANT_TRAITS_H
9#define SEN_CORE_META_VARIANT_TRAITS_H
10
11// sen
12#include "sen/core/base/span.h"
17#include "sen/core/meta/type.h"
19
20// std
21#include <cstring>
22#include <tuple>
23
24namespace sen
25{
26
27struct Var;
28
31
33{
34protected:
35 static void expectAtLeastOneField(const char* name, const Span<uint16_t>& fields);
36 [[noreturn]] static void throwNonNativeField(const char* variantName, const char* fieldName);
37 [[noreturn]] static void throwInvalidFieldIndex(const char* variantName, uint16_t index);
38 [[nodiscard]] static std::tuple<const char*, const Var*> getTypeAndValue(const Var& var,
40};
41
43template <typename T>
45{
46 static constexpr bool available = true;
47
48 template <std::size_t index>
49 [[nodiscard]] static bool tryPrintField(std::ostream& out, const char* typeName, const T& val, bool requiresNewline);
50
51protected:
52 template <std::size_t index>
53 [[nodiscard]] static bool assignFieldByName(const char* currentType,
54 const char* expectedTypeLong,
55 const char* expectedTypeShort,
56 const char* expectedAliasTypeShort,
57 const Var& fieldValue,
58 T& val);
59
60 template <std::size_t index>
61 static void assignField(const Var& fieldValue, T& val);
62
63 template <std::size_t index>
64 [[nodiscard]] static bool getFieldSerializedSize(const T& val, uint32_t key, uint32_t& result);
65
66 template <std::size_t index>
67 [[nodiscard]] static bool tryWriteField(OutputStream& out, const T& val, uint32_t key);
68
69 template <std::size_t index>
70 static void readField(InputStream& in, T& val);
71
72 template <std::size_t index>
73 [[nodiscard]] static bool tryFieldValueToVariant(const T& val, Var& var, std::shared_ptr<Var> valueVar, uint32_t key);
74};
75
77
78//----------------------------------------------------------------------------------------------------------------------
79// Inline implementation
80//----------------------------------------------------------------------------------------------------------------------
81
82template <typename T>
83template <std::size_t index>
84inline void VariantTraitsBase<T>::assignField(const Var& fieldValue, T& val)
85{
86 using F = std::variant_alternative_t<index, T>;
87 F fieldVal {};
88 VariantTraits<F>::variantToValue(fieldValue, fieldVal);
89 val.template emplace<index>(std::move(fieldVal));
90}
91
92template <typename T>
93template <std::size_t index>
94inline bool VariantTraitsBase<T>::assignFieldByName(const char* currentType,
95 const char* expectedTypeLong,
96 const char* expectedTypeShort,
97 const char* expectedAliasTypeShort,
98 const Var& fieldValue,
99 T& val)
100{
101 if (strcmp(currentType, expectedTypeShort) == 0U || strcmp(currentType, expectedTypeLong) == 0U ||
102 (expectedAliasTypeShort != nullptr && strcmp(currentType, expectedAliasTypeShort) == 0U))
103 {
104 assignField<index>(fieldValue, val);
105 return true;
106 }
107 return false;
108}
109
110template <typename T>
111template <std::size_t index>
112inline bool VariantTraitsBase<T>::getFieldSerializedSize(const T& val, uint32_t key, uint32_t& result)
113{
114 using F = std::variant_alternative_t<index, T>;
115 if (val.index() == index)
116 {
117 result =
119 return true;
120 }
121 return false;
122}
123
124template <typename T>
125template <std::size_t index>
126inline bool VariantTraitsBase<T>::tryWriteField(OutputStream& out, const T& val, uint32_t key)
127{
128 using F = std::variant_alternative_t<index, T>;
129 if (val.index() == index)
130 {
131 out.writeUInt32(key);
132 SerializationTraits<F>::write(out, std::get<index>(val));
133 return true;
134 }
135 return false;
136}
137
138template <typename T>
139template <std::size_t index>
141{
142 using F = std::variant_alternative_t<index, T>;
143 F fieldVal;
144 SerializationTraits<F>::read(in, fieldVal);
145 val.template emplace<index>(std::move(fieldVal));
146}
147
148template <typename T>
149template <std::size_t index>
151 Var& var,
152 std::shared_ptr<Var> valueVar,
153 uint32_t key)
154{
155 using F = std::variant_alternative_t<index, T>;
156 if (val.index() == index)
157 {
158 VariantTraits<F>::valueToVariant(std::get<index>(val), *valueVar);
159 var = KeyedVar {key, std::move(valueVar)};
160 return true;
161 }
162 return false;
163}
164
165template <typename T>
166template <std::size_t index>
167inline bool VariantTraitsBase<T>::tryPrintField(std::ostream& out,
168 const char* typeName,
169 const T& val,
170 bool requiresNewline)
171{
172 if (val.index() == index)
173 {
174 out.setf(std::ios::left, std::ios::adjustfield);
175
176 // The width is set straight on the stream before each padded item instead of being held in a
177 // std::setw object, which keeps <iomanip> out of a header every generated model pulls in. A
178 // width applies to the next item only, so it is set again for each one.
179 const auto indent = static_cast<int>(out.width() + 2U);
180
181 out.width(indent);
182 out << ' ' << "type: " << typeName << "\n";
183
184 if (auto valPtr = std::get_if<index>(&val); valPtr)
185 {
186 if (requiresNewline)
187 {
188 out.width(indent);
189 out << ' ' << "value:\n";
190 out.width(indent);
191 out << *valPtr;
192 }
193 else
194 {
195 out.width(indent);
196 out << ' ' << "value: " << *valPtr;
197 }
198 }
199 return true;
200 }
201 return false;
202}
203
204} // namespace sen
205
206#endif // SEN_CORE_META_VARIANT_TRAITS_H
void writeUInt32(uint32_t val)
Definition output_stream.h:44
Contiguous view of elements of type T. Inspired by http://www.open-std.org/jtc1/sc22/wg21/docs/papers...
Definition span.h:34
InputStreamTemplate< LittleEndian > InputStream
Definition input_stream.h:84
Definition type_traits.h:47
Definition type_traits.h:34
std::tuple< uint32_t, std::shared_ptr< Var > > KeyedVar
A key-var tuple, to represent variants.
Definition var.h:110
TypeHandle< const T > ConstTypeHandle
Definition type.h:319
Definition assert.h:19
OutputStreamTemplate< LittleEndian > OutputStream
Definition output_stream.h:64
Can hold any supported value type. Wraps std::variant to allow recursion and implements some helpers.
Definition var.h:119
Definition variant_traits.h:33
static void throwNonNativeField(const char *variantName, const char *fieldName)
static void throwInvalidFieldIndex(const char *variantName, uint16_t index)
static void expectAtLeastOneField(const char *name, const Span< uint16_t > &fields)
static std::tuple< const char *, const Var * > getTypeAndValue(const Var &var, ConstTypeHandle< VariantType > meta)
Base class for variant traits.
Definition variant_traits.h:45
static bool assignFieldByName(const char *currentType, const char *expectedTypeLong, const char *expectedTypeShort, const char *expectedAliasTypeShort, const Var &fieldValue, T &val)
Definition variant_traits.h:94
static bool tryWriteField(OutputStream &out, const T &val, uint32_t key)
Definition variant_traits.h:126
static void readField(InputStream &in, T &val)
Definition variant_traits.h:140
static constexpr bool available
Definition variant_traits.h:46
static bool tryPrintField(std::ostream &out, const char *typeName, const T &val, bool requiresNewline)
Definition variant_traits.h:167
static bool tryFieldValueToVariant(const T &val, Var &var, std::shared_ptr< Var > valueVar, uint32_t key)
Definition variant_traits.h:150
static bool getFieldSerializedSize(const T &val, uint32_t key, uint32_t &result)
Definition variant_traits.h:112
static void assignField(const Var &fieldValue, T &val)
Definition variant_traits.h:84