xref: /aosp_15_r20/external/google-fruit/include/fruit/impl/injector.defn.h (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker /*
2*a65addddSAndroid Build Coastguard Worker  * Copyright 2014 Google Inc. All rights reserved.
3*a65addddSAndroid Build Coastguard Worker  *
4*a65addddSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker  *
8*a65addddSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker  *
10*a65addddSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker  * limitations under the License.
15*a65addddSAndroid Build Coastguard Worker  */
16*a65addddSAndroid Build Coastguard Worker 
17*a65addddSAndroid Build Coastguard Worker #ifndef FRUIT_INJECTOR_DEFN_H
18*a65addddSAndroid Build Coastguard Worker #define FRUIT_INJECTOR_DEFN_H
19*a65addddSAndroid Build Coastguard Worker 
20*a65addddSAndroid Build Coastguard Worker #include <fruit/component.h>
21*a65addddSAndroid Build Coastguard Worker 
22*a65addddSAndroid Build Coastguard Worker // Redundant, but makes KDevelop happy.
23*a65addddSAndroid Build Coastguard Worker #include <fruit/injector.h>
24*a65addddSAndroid Build Coastguard Worker 
25*a65addddSAndroid Build Coastguard Worker namespace fruit {
26*a65addddSAndroid Build Coastguard Worker 
27*a65addddSAndroid Build Coastguard Worker template <typename... P>
28*a65addddSAndroid Build Coastguard Worker template <typename... FormalArgs, typename... Args>
Injector(Component<P...> (* getComponent)(FormalArgs...),Args &&...args)29*a65addddSAndroid Build Coastguard Worker inline Injector<P...>::Injector(Component<P...> (*getComponent)(FormalArgs...), Args&&... args) {
30*a65addddSAndroid Build Coastguard Worker   Component<P...> component = fruit::createComponent().install(getComponent, std::forward<Args>(args)...);
31*a65addddSAndroid Build Coastguard Worker 
32*a65addddSAndroid Build Coastguard Worker   fruit::impl::MemoryPool memory_pool;
33*a65addddSAndroid Build Coastguard Worker   using exposed_types_t = std::vector<fruit::impl::TypeId, fruit::impl::ArenaAllocator<fruit::impl::TypeId>>;
34*a65addddSAndroid Build Coastguard Worker   exposed_types_t exposed_types =
35*a65addddSAndroid Build Coastguard Worker       exposed_types_t(std::initializer_list<fruit::impl::TypeId>{fruit::impl::getTypeId<P>()...},
36*a65addddSAndroid Build Coastguard Worker                       fruit::impl::ArenaAllocator<fruit::impl::TypeId>(memory_pool));
37*a65addddSAndroid Build Coastguard Worker   storage = std::unique_ptr<fruit::impl::InjectorStorage>(
38*a65addddSAndroid Build Coastguard Worker       new fruit::impl::InjectorStorage(std::move(component.storage), exposed_types, memory_pool));
39*a65addddSAndroid Build Coastguard Worker }
40*a65addddSAndroid Build Coastguard Worker 
41*a65addddSAndroid Build Coastguard Worker namespace impl {
42*a65addddSAndroid Build Coastguard Worker namespace meta {
43*a65addddSAndroid Build Coastguard Worker 
44*a65addddSAndroid Build Coastguard Worker template <typename... P>
45*a65addddSAndroid Build Coastguard Worker struct InjectorImplHelper {
46*a65addddSAndroid Build Coastguard Worker 
47*a65addddSAndroid Build Coastguard Worker   // This performs all checks needed in the constructor of Injector that takes NormalizedComponent.
48*a65addddSAndroid Build Coastguard Worker   template <typename NormalizedComp, typename Comp>
49*a65addddSAndroid Build Coastguard Worker   struct CheckConstructionFromNormalizedComponent {
50*a65addddSAndroid Build Coastguard Worker     using Op = InstallComponent(Comp, NormalizedComp);
51*a65addddSAndroid Build Coastguard Worker 
52*a65addddSAndroid Build Coastguard Worker     // The calculation of MergedComp will also do some checks, e.g. multiple bindings for the same type.
53*a65addddSAndroid Build Coastguard Worker     using MergedComp = GetResult(Op);
54*a65addddSAndroid Build Coastguard Worker 
55*a65addddSAndroid Build Coastguard Worker     using TypesNotProvided = SetDifference(RemoveConstFromTypes(Vector<Type<P>...>), GetComponentPs(MergedComp));
56*a65addddSAndroid Build Coastguard Worker     using MergedCompRs = SetDifference(GetComponentRsSuperset(MergedComp), GetComponentPs(MergedComp));
57*a65addddSAndroid Build Coastguard Worker 
58*a65addddSAndroid Build Coastguard Worker     using type = Eval<If(
59*a65addddSAndroid Build Coastguard Worker         Not(IsEmptySet(GetComponentRsSuperset(Comp))),
60*a65addddSAndroid Build Coastguard Worker         ConstructErrorWithArgVector(ComponentWithRequirementsInInjectorErrorTag,
61*a65addddSAndroid Build Coastguard Worker                                     SetToVector(GetComponentRsSuperset(Comp))),
62*a65addddSAndroid Build Coastguard Worker         If(Not(IsEmptySet(MergedCompRs)),
63*a65addddSAndroid Build Coastguard Worker            ConstructErrorWithArgVector(UnsatisfiedRequirementsInNormalizedComponentErrorTag, SetToVector(MergedCompRs)),
64*a65addddSAndroid Build Coastguard Worker            If(Not(IsContained(VectorToSetUnchecked(RemoveConstFromTypes(Vector<Type<P>...>)),
65*a65addddSAndroid Build Coastguard Worker                               GetComponentPs(MergedComp))),
66*a65addddSAndroid Build Coastguard Worker               ConstructErrorWithArgVector(TypesInInjectorNotProvidedErrorTag, SetToVector(TypesNotProvided)),
67*a65addddSAndroid Build Coastguard Worker               If(Not(IsContained(VectorToSetUnchecked(RemoveConstTypes(Vector<Type<P>...>)),
68*a65addddSAndroid Build Coastguard Worker                                  GetComponentNonConstRsPs(MergedComp))),
69*a65addddSAndroid Build Coastguard Worker                  ConstructErrorWithArgVector(
70*a65addddSAndroid Build Coastguard Worker                      TypesInInjectorProvidedAsConstOnlyErrorTag,
71*a65addddSAndroid Build Coastguard Worker                      SetToVector(SetDifference(VectorToSetUnchecked(RemoveConstTypes(Vector<Type<P>...>)),
72*a65addddSAndroid Build Coastguard Worker                                                GetComponentNonConstRsPs(MergedComp)))),
73*a65addddSAndroid Build Coastguard Worker                  None))))>;
74*a65addddSAndroid Build Coastguard Worker   };
75*a65addddSAndroid Build Coastguard Worker 
76*a65addddSAndroid Build Coastguard Worker   template <typename T>
77*a65addddSAndroid Build Coastguard Worker   struct CheckGet {
78*a65addddSAndroid Build Coastguard Worker     using Comp = ConstructComponentImpl(Type<P>...);
79*a65addddSAndroid Build Coastguard Worker 
80*a65addddSAndroid Build Coastguard Worker     using type = Eval<PropagateError(CheckInjectableType(RemoveAnnotations(Type<T>)),
81*a65addddSAndroid Build Coastguard Worker                                      If(Not(IsInSet(NormalizeType(Type<T>), GetComponentPs(Comp))),
82*a65addddSAndroid Build Coastguard Worker                                         ConstructError(TypeNotProvidedErrorTag, Type<T>),
83*a65addddSAndroid Build Coastguard Worker                                         If(And(TypeInjectionRequiresNonConstBinding(Type<T>),
84*a65addddSAndroid Build Coastguard Worker                                                Not(IsInSet(NormalizeType(Type<T>), GetComponentNonConstRsPs(Comp)))),
85*a65addddSAndroid Build Coastguard Worker                                            ConstructError(TypeProvidedAsConstOnlyErrorTag, Type<T>), None)))>;
86*a65addddSAndroid Build Coastguard Worker   };
87*a65addddSAndroid Build Coastguard Worker };
88*a65addddSAndroid Build Coastguard Worker 
89*a65addddSAndroid Build Coastguard Worker } // namespace meta
90*a65addddSAndroid Build Coastguard Worker } // namespace impl
91*a65addddSAndroid Build Coastguard Worker 
92*a65addddSAndroid Build Coastguard Worker template <typename... P>
93*a65addddSAndroid Build Coastguard Worker template <typename... NormalizedComponentParams, typename... ComponentParams, typename... FormalArgs, typename... Args>
Injector(const NormalizedComponent<NormalizedComponentParams...> & normalized_component,Component<ComponentParams...> (* getComponent)(FormalArgs...),Args &&...args)94*a65addddSAndroid Build Coastguard Worker inline Injector<P...>::Injector(const NormalizedComponent<NormalizedComponentParams...>& normalized_component,
95*a65addddSAndroid Build Coastguard Worker                                 Component<ComponentParams...> (*getComponent)(FormalArgs...), Args&&... args) {
96*a65addddSAndroid Build Coastguard Worker   Component<ComponentParams...> component = fruit::createComponent().install(getComponent, std::forward<Args>(args)...);
97*a65addddSAndroid Build Coastguard Worker 
98*a65addddSAndroid Build Coastguard Worker   fruit::impl::MemoryPool memory_pool;
99*a65addddSAndroid Build Coastguard Worker   storage = std::unique_ptr<fruit::impl::InjectorStorage>(new fruit::impl::InjectorStorage(
100*a65addddSAndroid Build Coastguard Worker       *(normalized_component.storage.storage), std::move(component.storage), memory_pool));
101*a65addddSAndroid Build Coastguard Worker 
102*a65addddSAndroid Build Coastguard Worker   using NormalizedComp =
103*a65addddSAndroid Build Coastguard Worker       fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type<NormalizedComponentParams>...);
104*a65addddSAndroid Build Coastguard Worker   using Comp1 = fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type<ComponentParams>...);
105*a65addddSAndroid Build Coastguard Worker   // We don't check whether the construction of NormalizedComp or Comp resulted in errors here; if they did, the
106*a65addddSAndroid Build Coastguard Worker   // instantiation
107*a65addddSAndroid Build Coastguard Worker   // of NormalizedComponent<NormalizedComponentParams...> or Component<ComponentParams...> would have resulted in an
108*a65addddSAndroid Build Coastguard Worker   // error already.
109*a65addddSAndroid Build Coastguard Worker 
110*a65addddSAndroid Build Coastguard Worker   using E = typename fruit::impl::meta::InjectorImplHelper<P...>::template CheckConstructionFromNormalizedComponent<
111*a65addddSAndroid Build Coastguard Worker       NormalizedComp, Comp1>::type;
112*a65addddSAndroid Build Coastguard Worker   (void)typename fruit::impl::meta::CheckIfError<E>::type();
113*a65addddSAndroid Build Coastguard Worker }
114*a65addddSAndroid Build Coastguard Worker 
115*a65addddSAndroid Build Coastguard Worker template <typename... P>
116*a65addddSAndroid Build Coastguard Worker template <typename T>
get()117*a65addddSAndroid Build Coastguard Worker inline fruit::impl::RemoveAnnotations<T> Injector<P...>::get() {
118*a65addddSAndroid Build Coastguard Worker   using E = typename fruit::impl::meta::InjectorImplHelper<P...>::template CheckGet<T>::type;
119*a65addddSAndroid Build Coastguard Worker   (void)typename fruit::impl::meta::CheckIfError<E>::type();
120*a65addddSAndroid Build Coastguard Worker   return storage->template get<T>();
121*a65addddSAndroid Build Coastguard Worker }
122*a65addddSAndroid Build Coastguard Worker 
123*a65addddSAndroid Build Coastguard Worker template <typename... P>
124*a65addddSAndroid Build Coastguard Worker template <typename T>
T()125*a65addddSAndroid Build Coastguard Worker inline Injector<P...>::operator T() {
126*a65addddSAndroid Build Coastguard Worker   return get<T>();
127*a65addddSAndroid Build Coastguard Worker }
128*a65addddSAndroid Build Coastguard Worker 
129*a65addddSAndroid Build Coastguard Worker template <typename... P>
130*a65addddSAndroid Build Coastguard Worker template <typename AnnotatedC>
getMultibindings()131*a65addddSAndroid Build Coastguard Worker inline const std::vector<fruit::impl::RemoveAnnotations<AnnotatedC>*>& Injector<P...>::getMultibindings() {
132*a65addddSAndroid Build Coastguard Worker 
133*a65addddSAndroid Build Coastguard Worker   using Op = fruit::impl::meta::Eval<fruit::impl::meta::CheckNormalizedTypes(
134*a65addddSAndroid Build Coastguard Worker       fruit::impl::meta::Vector<fruit::impl::meta::Type<AnnotatedC>>)>;
135*a65addddSAndroid Build Coastguard Worker   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
136*a65addddSAndroid Build Coastguard Worker 
137*a65addddSAndroid Build Coastguard Worker   return storage->template getMultibindings<AnnotatedC>();
138*a65addddSAndroid Build Coastguard Worker }
139*a65addddSAndroid Build Coastguard Worker 
140*a65addddSAndroid Build Coastguard Worker template <typename... P>
FRUIT_DEPRECATED_DEFINITION(inline void Injector<P...>::eagerlyInjectAll ())141*a65addddSAndroid Build Coastguard Worker FRUIT_DEPRECATED_DEFINITION(inline void Injector<P...>::eagerlyInjectAll()) {
142*a65addddSAndroid Build Coastguard Worker   // Eagerly inject normal bindings.
143*a65addddSAndroid Build Coastguard Worker   void* unused[] = {reinterpret_cast<void*>(
144*a65addddSAndroid Build Coastguard Worker       storage->template get<fruit::impl::meta::UnwrapType<
145*a65addddSAndroid Build Coastguard Worker           fruit::impl::meta::Eval<fruit::impl::meta::AddPointerInAnnotatedType(fruit::impl::meta::Type<P>)>>>())...};
146*a65addddSAndroid Build Coastguard Worker   (void)unused;
147*a65addddSAndroid Build Coastguard Worker 
148*a65addddSAndroid Build Coastguard Worker   storage->eagerlyInjectMultibindings();
149*a65addddSAndroid Build Coastguard Worker }
150*a65addddSAndroid Build Coastguard Worker 
151*a65addddSAndroid Build Coastguard Worker } // namespace fruit
152*a65addddSAndroid Build Coastguard Worker 
153*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_INJECTOR_DEFN_H
154