generated from userver-framework/service_template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
reflective.hpp
71 lines (66 loc) · 2.49 KB
/
reflective.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#pragma once
#include <openapi/base/properties/optional.hpp>
#include <openapi/base/reflective/preferences.hpp>
#include <openapi/base/reflective/utils.hpp>
#include <openapi/doc/base.hpp>
#include <type_traits>
namespace openapi
{
template <typename T>
void AppendField(DocHelper doc_helper, std::type_identity<T> type)
{
constexpr auto& Traits = T::traits;
constexpr auto name_ce = traits::GetName(Traits);
constexpr auto name_ce_empty = name_ce.empty();
static_assert(!name_ce_empty, "Field must have name");
std::string name{name_ce.AsStringView()};
auto field_node = doc_helper.cur_place["properties"][name];
auto matcher = userver::utils::Overloaded{
[&]<typename U>(std::type_identity<U>) {
auto required = doc_helper.cur_place["required"];
if (!required.IsArray())
required = userver::formats::common::Type::kArray;
required.PushBack(name);
},
[]<typename U, auto Traits>(
std::type_identity<OptionalProperty<U, Traits>>){}};
matcher(type);
Append(DocHelper{doc_helper.root, field_node}, std::type_identity<T>{});
}
// noop, пропускаем
template <>
inline void AppendField(DocHelper, std::type_identity<AdditionalProperties>)
{
}
template <typename T>
requires checks::is_reflective_v<T> void Append(DocHelper doc_helper,
std::type_identity<T>)
{
std::string name_type = GetOpenApiTypeName<T>();
if (&doc_helper.cur_place != &doc_helper.root)
{
PlaceRefToType<T>(doc_helper.cur_place);
}
auto type_node = doc_helper.root["components"]["schemas"][name_type];
if (!type_node.IsObject())
{
type_node = userver::formats::common::Type::kObject;
type_node["type"] = "object";
constexpr checks::ReflectivePreferences<T> pref{};
bool additional_properties = (pref.additional_properties_status ==
checks::AdditionalPropertiesStatus::True);
type_node["additionalProperties"] = additional_properties;
auto dock_helper = DocHelper{doc_helper.root, type_node};
auto visiter_fields = [dock_helper](auto field) {
AppendField(dock_helper, field);
};
CallAllFields<T>(visiter_fields);
}
}
template <typename T>
requires checks::is_reflective_v<T> void Append(Doc& doc, std::type_identity<T>)
{
auto& root = doc.value_;
Append(DocHelper{root, root}, std::type_identity<T>{});
}
} // namespace openapi