11#include <userver/components/component_fwd.hpp>
12#include <userver/components/static_config_validator.hpp>
14USERVER_NAMESPACE_BEGIN
21auto NameRegistrationFromComponentType() ->
decltype(std::string_view{T::kName}) {
22 return std::string_view{T::kName};
25template <
class T,
class... Args>
26auto NameRegistrationFromComponentType(Args...) {
29 "Component does not have a 'kName' member convertible to "
30 "std::string_view. You have to explicitly specify the name: "
31 "component_list.Append<T>(name)."
33 return std::string_view{};
36class ComponentAdderBase {
38 ComponentAdderBase() =
delete;
39 ComponentAdderBase(
const ComponentAdderBase&) =
delete;
40 ComponentAdderBase(ComponentAdderBase&&) =
delete;
41 ComponentAdderBase& operator=(
const ComponentAdderBase&) =
delete;
42 ComponentAdderBase& operator=(ComponentAdderBase&&) =
delete;
44 ComponentAdderBase(std::string name,
ConfigFileMode config_file_mode);
46 virtual ~ComponentAdderBase();
48 const std::string& GetComponentName()
const noexcept {
return name_; }
50 ConfigFileMode GetConfigFileMode()
const {
return config_file_mode_; }
53 const ComponentConfig& config,
54 const ComponentContext& context
57 virtual void ValidateStaticConfig(
const ComponentConfig&, ValidationMode)
const = 0;
59 virtual yaml_config::Schema GetStaticConfigSchema()
const = 0;
66template <
typename Component>
67class ComponentAdder
final :
public ComponentAdderBase {
73 "Component should publicly inherit from components::ComponentBase"
74 " and the component definition should be visible at its registration"
77 explicit ComponentAdder(std::string name)
78 : ComponentAdderBase(std::move(name), kConfigFileMode<Component>)
81 std::unique_ptr<
RawComponentBase> MakeComponent(
const ComponentConfig& config,
const ComponentContext& context)
83 return std::make_unique<Component>(config, context);
86 void ValidateStaticConfig(
const ComponentConfig& static_config, ValidationMode validation_mode)
const override {
87 impl::TryValidateStaticConfig<Component>(GetComponentName(), static_config, validation_mode);
90 yaml_config::Schema GetStaticConfigSchema()
const override {
return impl::GetStaticConfigSchema<Component>(); }
93using ComponentAdderPtr = std::unique_ptr<
const impl::ComponentAdderBase>;
95struct ComponentAdderComparator {
96 using is_transparent = std::true_type;
98 static std::string_view ToStringView(
const ComponentAdderPtr& x)
noexcept {
99 return std::string_view{x->GetComponentName()};
102 static std::string_view ToStringView(std::string_view x)
noexcept {
return x; }
104 template <
class T,
class U>
105 bool operator()(
const T& x,
const U& y)
const noexcept {
106 return ToStringView(x) < ToStringView(y);
114class ComponentList
final {
117 template <
typename Component>
118 ComponentList&
Append() &;
121 template <
typename Component>
122 ComponentList&
Append(std::string_view name) &;
131 template <
typename Component,
typename... Args>
135 bool Contains(std::string_view name)
const {
return adders_.count(name) > 0; }
138 using Adders = std::set<impl::ComponentAdderPtr, impl::ComponentAdderComparator>;
140 Adders::const_iterator begin()
const {
return adders_.begin(); }
141 Adders::const_iterator end()
const {
return adders_.end(); }
143 ComponentList& Append(impl::ComponentAdderPtr&& added) &;
152template <
typename Component>
153ComponentList& ComponentList::
Append() & {
154 return Append<Component>(impl::NameRegistrationFromComponentType<Component>());
157template <
typename Component>
158ComponentList& ComponentList::
Append(std::string_view name) & {
159 using Adder = impl::ComponentAdder<Component>;
160 auto adder = std::make_unique<
const Adder>(std::string{name});
161 return Append(std::move(adder));
164template <
typename Component,
typename... Args>
165ComponentList&& ComponentList::
Append(Args&&... args) && {
166 return std::move(Append<Component>(std::forward<Args>(args)...));