blob: 0e4b98c8e10b426749bf4006f2457059b71e0da5 [file] [log] [blame]
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FRUIT_PARTIAL_COMPONENT_STORAGE_DEFN_H
#define FRUIT_PARTIAL_COMPONENT_STORAGE_DEFN_H
#include <fruit/impl/component_storage/partial_component_storage.h>
#include <fruit/impl/bindings.h>
#include <fruit/impl/injector/injector_storage.h>
#include <fruit/impl/util/call_with_tuple.h>
#include <fruit/impl/util/type_info.h>
#include <utility>
namespace fruit {
namespace impl {
template <>
class PartialComponentStorage<> {
public:
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
(void)entries;
}
std::size_t numBindings() const {
return 0;
}
};
template <typename I, typename C, typename... PreviousBindings>
class PartialComponentStorage<Bind<I, C>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor)
: previous_storage(previous_storage) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings();
}
};
template <typename Signature, typename... PreviousBindings>
class PartialComponentStorage<RegisterConstructor<Signature>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor)
: previous_storage(previous_storage) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings();
}
};
template <typename C, typename C1, typename... PreviousBindings>
class PartialComponentStorage<BindInstance<C, C1>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
C& instance;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, C& instance)
: previous_storage(previous_storage), instance(instance) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(InjectorStorage::createComponentStorageEntryForBindInstance<C, C>(instance));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename C, typename C1, typename... PreviousBindings>
class PartialComponentStorage<BindConstInstance<C, C1>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
const C& instance;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, const C& instance)
: previous_storage(previous_storage), instance(instance) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(InjectorStorage::createComponentStorageEntryForBindConstInstance<C, C>(instance));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename C, typename Annotation, typename C1, typename... PreviousBindings>
class PartialComponentStorage<BindInstance<fruit::Annotated<Annotation, C>, C1>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
C& instance;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, C& instance)
: previous_storage(previous_storage), instance(instance) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(
InjectorStorage::createComponentStorageEntryForBindInstance<fruit::Annotated<Annotation, C>, C>(instance));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename C, typename Annotation, typename C1, typename... PreviousBindings>
class PartialComponentStorage<BindConstInstance<fruit::Annotated<Annotation, C>, C1>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
const C& instance;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, const C& instance)
: previous_storage(previous_storage), instance(instance) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(
InjectorStorage::createComponentStorageEntryForBindConstInstance<fruit::Annotated<Annotation, C>, C>(instance));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename... Params, typename... PreviousBindings>
class PartialComponentStorage<RegisterProvider<Params...>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor)
: previous_storage(previous_storage) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings();
}
};
template <typename C, typename... PreviousBindings>
class PartialComponentStorage<AddInstanceMultibinding<C>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
C& instance;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, C& instance)
: previous_storage(previous_storage), instance(instance) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(InjectorStorage::createComponentStorageEntryForInstanceMultibinding<C, C>(instance));
entries.push_back(InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<C>());
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 2;
}
};
template <typename C, typename Annotation, typename... PreviousBindings>
class PartialComponentStorage<AddInstanceMultibinding<fruit::Annotated<Annotation, C>>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
C& instance;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, C& instance)
: previous_storage(previous_storage), instance(instance) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(
InjectorStorage::createComponentStorageEntryForInstanceMultibinding<fruit::Annotated<Annotation, C>, C>(
instance));
entries.push_back(
InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<fruit::Annotated<Annotation, C>>());
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 2;
}
};
template <typename C, typename... PreviousBindings>
class PartialComponentStorage<AddInstanceVectorMultibindings<C>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
std::vector<C>& instances;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, std::vector<C>& instances)
: previous_storage(previous_storage), instances(instances) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
for (auto i = instances.rbegin(), i_end = instances.rend(); i != i_end; ++i) {
// TODO: consider optimizing this so that we need just 1 MULTIBINDING_VECTOR_CREATOR entry (removing the
// assumption that each multibinding entry is always preceded by that).
entries.push_back(InjectorStorage::createComponentStorageEntryForInstanceMultibinding<C, C>(*i));
entries.push_back(InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<C>());
}
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + instances.size() * 2;
}
};
template <typename C, typename Annotation, typename... PreviousBindings>
class PartialComponentStorage<AddInstanceVectorMultibindings<fruit::Annotated<Annotation, C>>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
std::vector<C>& instances;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, std::vector<C>& instances)
: previous_storage(previous_storage), instances(instances) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
for (auto i = instances.rbegin(), i_end = instances.rend(); i != i_end; ++i) {
// TODO: consider optimizing this so that we need just 1 MULTIBINDING_VECTOR_CREATOR entry (removing the
// assumption that each multibinding entry is always preceded by that).
entries.push_back(
InjectorStorage::createComponentStorageEntryForInstanceMultibinding<fruit::Annotated<Annotation, C>, C>(*i));
entries.push_back(
InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<fruit::Annotated<Annotation, C>>());
}
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + instances.size() * 2;
}
};
template <typename I, typename C, typename... PreviousBindings>
class PartialComponentStorage<AddMultibinding<I, C>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor)
: previous_storage(previous_storage) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings();
}
};
template <typename... Params, typename... PreviousBindings>
class PartialComponentStorage<AddMultibindingProvider<Params...>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor)
: previous_storage(previous_storage) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings();
}
};
template <typename DecoratedSignature, typename Lambda, typename... PreviousBindings>
class PartialComponentStorage<RegisterFactory<DecoratedSignature, Lambda>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage) // NOLINT(google-explicit-constructor)
: previous_storage(previous_storage) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings();
}
};
template <typename OtherComponent, typename... PreviousBindings>
class PartialComponentStorage<InstallComponent<OtherComponent()>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
OtherComponent (*fun)();
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, OtherComponent (*fun1)(),
std::tuple<>)
: previous_storage(previous_storage), fun(fun1) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(ComponentStorageEntry::LazyComponentWithNoArgs::create(fun));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename OtherComponent, typename... Args, typename... PreviousBindings>
class PartialComponentStorage<InstallComponent<OtherComponent(Args...)>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
OtherComponent (*fun)(Args...);
std::tuple<Args...> args_tuple;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage,
OtherComponent (*fun1)(Args...), std::tuple<Args...> args_tuple)
: previous_storage(previous_storage), fun(fun1), args_tuple(std::move(args_tuple)) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) {
entries.push_back(ComponentStorageEntry::LazyComponentWithArgs::create(fun, std::move(args_tuple)));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <std::size_t i, typename ComponentFunctionsTuple>
struct AddAllComponentStorageEntries {
inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries,
ComponentFunctionsTuple& component_functions_tuple) {
AddAllComponentStorageEntries<i - 1, ComponentFunctionsTuple>()(entries, component_functions_tuple);
entries.push_back(createEntry(std::move(std::get<i - 1>(component_functions_tuple))));
}
template <typename ComponentType>
inline ComponentStorageEntry createEntry(
fruit::ComponentFunction<ComponentType> component_function) {
return ComponentStorageEntry::LazyComponentWithNoArgs::create(std::move(component_function));
}
template <typename ComponentType, typename Arg, typename... Args>
inline ComponentStorageEntry createEntry(
fruit::ComponentFunction<ComponentType, Arg, Args...> component_function) {
return ComponentStorageEntry::LazyComponentWithArgs::create(std::move(component_function));
}
};
template <typename ComponentFunctionsTuple>
struct AddAllComponentStorageEntries<0, ComponentFunctionsTuple> {
inline void operator()(FixedSizeVector<ComponentStorageEntry>&,
ComponentFunctionsTuple&) {}
};
template <typename ComponentFunctionsTuple>
void addAllComponentStorageEntries(FixedSizeVector<ComponentStorageEntry>& entries,
ComponentFunctionsTuple&& component_functions_tuple) {
AddAllComponentStorageEntries<std::tuple_size<ComponentFunctionsTuple>::value,
ComponentFunctionsTuple>()(
entries, component_functions_tuple);
}
template <typename... ComponentFunctions, typename... PreviousBindings>
class PartialComponentStorage<InstallComponentFunctions<ComponentFunctions...>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
std::tuple<ComponentFunctions...> component_functions_tuple;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage,
std::tuple<ComponentFunctions...> component_functions_tuple)
: previous_storage(previous_storage), component_functions_tuple(std::move(component_functions_tuple)) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) {
addAllComponentStorageEntries(entries, std::move(component_functions_tuple));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + sizeof...(ComponentFunctions);
}
};
template <typename OtherComponent, typename... PreviousBindings>
class PartialComponentStorage<PartialReplaceComponent<OtherComponent()>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
OtherComponent (*fun)();
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage, OtherComponent (*fun1)(),
std::tuple<>)
: previous_storage(previous_storage), fun(fun1) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(ComponentStorageEntry::LazyComponentWithNoArgs::createReplacedComponentEntry(fun));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename OtherComponent, typename... ReplacedFunArgs, typename... PreviousBindings>
class PartialComponentStorage<PartialReplaceComponent<OtherComponent(ReplacedFunArgs...)>, PreviousBindings...> {
private:
PartialComponentStorage<PreviousBindings...>& previous_storage;
OtherComponent (*fun)(ReplacedFunArgs...);
std::tuple<ReplacedFunArgs...> args_tuple;
public:
PartialComponentStorage(PartialComponentStorage<PreviousBindings...>& previous_storage,
OtherComponent (*fun1)(ReplacedFunArgs...), std::tuple<ReplacedFunArgs...> args_tuple)
: previous_storage(previous_storage), fun(fun1), args_tuple(std::move(args_tuple)) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) {
entries.push_back(
ComponentStorageEntry::LazyComponentWithArgs::createReplacedComponentEntry(fun, std::move(args_tuple)));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename OtherComponent, typename... PreviousBindings, typename... ReplacedFunArgs>
class PartialComponentStorage<ReplaceComponent<OtherComponent(ReplacedFunArgs...), OtherComponent()>,
PreviousBindings...> {
private:
using previous_storage_t =
PartialComponentStorage<PartialReplaceComponent<OtherComponent(ReplacedFunArgs...)>, PreviousBindings...>;
previous_storage_t& previous_storage;
OtherComponent (*fun)();
public:
PartialComponentStorage(previous_storage_t& previous_storage, OtherComponent (*fun1)(), std::tuple<>)
: previous_storage(previous_storage), fun(fun1) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) const {
entries.push_back(ComponentStorageEntry::LazyComponentWithNoArgs::createReplacementComponentEntry(fun));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
template <typename OtherComponent, typename... ReplacedFunArgs, typename... ReplacementFunArgs,
typename... PreviousBindings>
class PartialComponentStorage<
ReplaceComponent<OtherComponent(ReplacedFunArgs...), OtherComponent(ReplacementFunArgs...)>, PreviousBindings...> {
private:
using previous_storage_t =
PartialComponentStorage<PartialReplaceComponent<OtherComponent(ReplacedFunArgs...)>, PreviousBindings...>;
previous_storage_t& previous_storage;
OtherComponent (*fun)(ReplacementFunArgs...);
std::tuple<ReplacementFunArgs...> args_tuple;
public:
PartialComponentStorage(previous_storage_t& previous_storage, OtherComponent (*fun1)(ReplacementFunArgs...),
std::tuple<ReplacementFunArgs...> args_tuple)
: previous_storage(previous_storage), fun(fun1), args_tuple(std::move(args_tuple)) {}
void addBindings(FixedSizeVector<ComponentStorageEntry>& entries) {
entries.push_back(
ComponentStorageEntry::LazyComponentWithArgs::createReplacementComponentEntry(fun, std::move(args_tuple)));
previous_storage.addBindings(entries);
}
std::size_t numBindings() const {
return previous_storage.numBindings() + 1;
}
};
} // namespace impl
} // namespace fruit
#endif // FRUIT_PARTIAL_COMPONENT_STORAGE_DEFN_H