• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef FRUIT_COMPONENT_DEFN_H
18 #define FRUIT_COMPONENT_DEFN_H
19 
20 #include <fruit/component.h>
21 
22 #include <fruit/impl/component_storage/component_storage.h>
23 #include <fruit/impl/injection_errors.h>
24 #include <fruit/impl/component_install_arg_checks.h>
25 
26 #include <memory>
27 
28 namespace fruit {
29 
30 namespace impl {
31 namespace meta {
32 // This is a helper class used in the implementation of Component and PartialComponent.
33 // It's in fruit::impl::meta so that we don't need to qualify everything with fruit::impl::meta.
34 template <typename... PreviousBindings>
35 struct OpForComponent {
36   template <typename Comp>
37   using ConvertTo = Eval<Call(ReverseComposeFunctors(Id<ComponentFunctor(ConvertComponent, Comp)>,
38                                                      ProcessDeferredBindings, Id<ProcessBinding(PreviousBindings)>...),
39                               ConstructComponentImpl())>;
40 
41   template <typename Binding>
42   using AddBinding =
43       Eval<Call(ReverseComposeFunctors(Id<ProcessBinding(Binding)>, Id<ProcessBinding(PreviousBindings)>...),
44                 ConstructComponentImpl())>;
45 };
46 } // namespace meta
47 } // namespace impl
48 
49 template <typename... Params>
50 template <typename... Bindings>
Component(PartialComponent<Bindings...> && partial_component)51 inline Component<Params...>::Component(PartialComponent<Bindings...>&& partial_component) : storage() {
52 
53   (void)typename fruit::impl::meta::CheckIfError<Comp>::type();
54 
55   using Op = typename fruit::impl::meta::OpForComponent<Bindings...>::template ConvertTo<Comp>;
56   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
57 
58 #if !FRUIT_NO_LOOP_CHECK
59   (void)typename fruit::impl::meta::CheckIfError<
60       fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op::Result)>>::type();
61 #endif // !FRUIT_NO_LOOP_CHECK
62 
63   std::size_t num_entries = partial_component.storage.numBindings() + Op().numEntries();
64   fruit::impl::FixedSizeVector<fruit::impl::ComponentStorageEntry> entries(num_entries);
65 
66   Op()(entries);
67 
68   // addBindings may modify the storage member of PartialComponent.
69   // Therefore, it should not be used after this operation.
70   partial_component.storage.addBindings(entries);
71 
72   // TODO: re-enable this check somehow.
73   // component.component.already_converted_to_component = true;
74 
75   FruitAssert(entries.size() == num_entries);
76 
77   storage = fruit::impl::ComponentStorage(std::move(entries));
78 }
79 
80 template <typename... Bindings>
~PartialComponent()81 inline PartialComponent<Bindings...>::~PartialComponent() {}
82 
createComponent()83 inline PartialComponent<> createComponent() {
84   return {{}};
85 }
86 
87 template <typename... Bindings>
88 template <typename AnnotatedI, typename AnnotatedC>
bind()89 inline PartialComponent<fruit::impl::Bind<AnnotatedI, AnnotatedC>, Bindings...> PartialComponent<Bindings...>::bind() {
90   using Op = OpFor<fruit::impl::Bind<AnnotatedI, AnnotatedC>>;
91   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
92 
93   return {{storage}};
94 }
95 
96 template <typename... Bindings>
97 template <typename AnnotatedSignature>
98 inline PartialComponent<fruit::impl::RegisterConstructor<AnnotatedSignature>, Bindings...>
registerConstructor()99 PartialComponent<Bindings...>::registerConstructor() {
100   using Op = OpFor<fruit::impl::RegisterConstructor<AnnotatedSignature>>;
101   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
102 
103   return {{storage}};
104 }
105 
106 template <typename... Bindings>
107 template <typename C>
108 inline PartialComponent<fruit::impl::BindInstance<C, C>, Bindings...>
bindInstance(C & instance)109 PartialComponent<Bindings...>::bindInstance(C& instance) {
110   using Op = OpFor<fruit::impl::BindInstance<C, C>>;
111   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
112   return {{storage, instance}};
113 }
114 
115 template <typename... Bindings>
116 template <typename C>
117 inline PartialComponent<fruit::impl::BindConstInstance<C, C>, Bindings...>
bindInstance(const C & instance)118 PartialComponent<Bindings...>::bindInstance(const C& instance) {
119   using Op = OpFor<fruit::impl::BindConstInstance<C, C>>;
120   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
121   return {{storage, instance}};
122 }
123 
124 template <typename... Bindings>
125 template <typename AnnotatedC, typename C>
126 inline PartialComponent<fruit::impl::BindInstance<AnnotatedC, C>, Bindings...>
bindInstance(C & instance)127 PartialComponent<Bindings...>::bindInstance(C& instance) {
128   using Op = OpFor<fruit::impl::BindInstance<AnnotatedC, C>>;
129   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
130   return {{storage, instance}};
131 }
132 
133 template <typename... Bindings>
134 template <typename AnnotatedC, typename C>
135 inline PartialComponent<fruit::impl::BindConstInstance<AnnotatedC, C>, Bindings...>
bindInstance(const C & instance)136 PartialComponent<Bindings...>::bindInstance(const C& instance) {
137   using Op = OpFor<fruit::impl::BindConstInstance<AnnotatedC, C>>;
138   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
139   return {{storage, instance}};
140 }
141 
142 template <typename... Bindings>
143 template <typename Lambda>
144 inline PartialComponent<fruit::impl::RegisterProvider<Lambda>, Bindings...>
registerProvider(Lambda)145 PartialComponent<Bindings...>::registerProvider(Lambda) {
146   using Op = OpFor<fruit::impl::RegisterProvider<Lambda>>;
147   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
148   return {{storage}};
149 }
150 
151 template <typename... Bindings>
152 template <typename AnnotatedSignature, typename Lambda>
153 inline PartialComponent<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>, Bindings...>
registerProvider(Lambda)154 PartialComponent<Bindings...>::registerProvider(Lambda) {
155   using Op = OpFor<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>>;
156   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
157   return {{storage}};
158 }
159 
160 template <typename... Bindings>
161 template <typename AnnotatedI, typename AnnotatedC>
162 inline PartialComponent<fruit::impl::AddMultibinding<AnnotatedI, AnnotatedC>, Bindings...>
addMultibinding()163 PartialComponent<Bindings...>::addMultibinding() {
164   using Op = OpFor<fruit::impl::AddMultibinding<AnnotatedI, AnnotatedC>>;
165   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
166 
167   return {{storage}};
168 }
169 
170 template <typename... Bindings>
171 template <typename C>
172 inline PartialComponent<fruit::impl::AddInstanceMultibinding<C>, Bindings...>
addInstanceMultibinding(C & instance)173 PartialComponent<Bindings...>::addInstanceMultibinding(C& instance) {
174   using Op = fruit::impl::meta::Eval<fruit::impl::meta::CheckNormalizedTypes(
175       fruit::impl::meta::Vector<fruit::impl::meta::Type<C>>)>;
176   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
177 
178   return {{storage, instance}};
179 }
180 
181 template <typename... Bindings>
182 template <typename AnnotatedC, typename C>
183 inline PartialComponent<fruit::impl::AddInstanceMultibinding<AnnotatedC>, Bindings...>
addInstanceMultibinding(C & instance)184 PartialComponent<Bindings...>::addInstanceMultibinding(C& instance) {
185   using Op = fruit::impl::meta::Eval<fruit::impl::meta::CheckNormalizedTypes(
186       fruit::impl::meta::Vector<fruit::impl::meta::Type<C>>)>;
187   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
188   return {{storage, instance}};
189 }
190 
191 template <typename... Bindings>
192 template <typename C>
193 inline PartialComponent<fruit::impl::AddInstanceVectorMultibindings<C>, Bindings...>
addInstanceMultibindings(std::vector<C> & instances)194 PartialComponent<Bindings...>::addInstanceMultibindings(std::vector<C>& instances) {
195   using Op = fruit::impl::meta::Eval<fruit::impl::meta::CheckNormalizedTypes(
196       fruit::impl::meta::Vector<fruit::impl::meta::Type<C>>)>;
197   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
198   return {{storage, instances}};
199 }
200 
201 template <typename... Bindings>
202 template <typename AnnotatedC, typename C>
203 inline PartialComponent<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>, Bindings...>
addInstanceMultibindings(std::vector<C> & instances)204 PartialComponent<Bindings...>::addInstanceMultibindings(std::vector<C>& instances) {
205   using Op = fruit::impl::meta::Eval<fruit::impl::meta::CheckNormalizedTypes(
206       fruit::impl::meta::Vector<fruit::impl::meta::Type<C>>)>;
207   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
208 
209   return {{storage, instances}};
210 }
211 
212 template <typename... Bindings>
213 template <typename Lambda>
214 inline PartialComponent<fruit::impl::AddMultibindingProvider<Lambda>, Bindings...>
addMultibindingProvider(Lambda)215 PartialComponent<Bindings...>::addMultibindingProvider(Lambda) {
216   using Op = OpFor<fruit::impl::AddMultibindingProvider<Lambda>>;
217   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
218 
219   return {{storage}};
220 }
221 
222 template <typename... Bindings>
223 template <typename AnnotatedSignature, typename Lambda>
224 inline PartialComponent<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>, Bindings...>
addMultibindingProvider(Lambda)225 PartialComponent<Bindings...>::addMultibindingProvider(Lambda) {
226   using Op = OpFor<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>>;
227   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
228 
229   return {{storage}};
230 }
231 
232 template <typename... Bindings>
233 template <typename DecoratedSignature, typename Lambda>
234 inline PartialComponent<fruit::impl::RegisterFactory<DecoratedSignature, Lambda>, Bindings...>
registerFactory(Lambda)235 PartialComponent<Bindings...>::registerFactory(Lambda) {
236   using Op = OpFor<fruit::impl::RegisterFactory<DecoratedSignature, Lambda>>;
237   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
238 
239   return {{storage}};
240 }
241 
242 template <typename... Bindings>
PartialComponent(fruit::impl::PartialComponentStorage<Bindings...> storage)243 inline PartialComponent<Bindings...>::PartialComponent(fruit::impl::PartialComponentStorage<Bindings...> storage)
244     : storage(std::move(storage)) {}
245 
246 template <typename... Bindings>
247 template <typename... OtherComponentParams, typename... FormalArgs, typename... Args>
248 inline PartialComponent<fruit::impl::InstallComponent<fruit::Component<OtherComponentParams...>(FormalArgs...)>,
249                         Bindings...>
install(fruit::Component<OtherComponentParams...> (* getComponent)(FormalArgs...),Args &&...args)250 PartialComponent<Bindings...>::install(fruit::Component<OtherComponentParams...> (*getComponent)(FormalArgs...),
251                                        Args&&... args) {
252   using IntCollector = int[];
253   (void)IntCollector{0, fruit::impl::checkAcceptableComponentInstallArg<FormalArgs>()...};
254 
255   using Op = OpFor<fruit::impl::InstallComponent<fruit::Component<OtherComponentParams...>(FormalArgs...)>>;
256   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
257 
258   std::tuple<FormalArgs...> args_tuple{std::forward<Args>(args)...};
259 
260   return {{storage, getComponent, std::move(args_tuple)}};
261 }
262 
263 template <typename... Bindings>
264 template <typename... ComponentFunctions>
265 inline PartialComponent<fruit::impl::InstallComponentFunctions<ComponentFunctions...>, Bindings...>
installComponentFunctions(ComponentFunctions...componentFunctions)266 PartialComponent<Bindings...>::installComponentFunctions(ComponentFunctions... componentFunctions) {
267 
268   using Op = OpFor<fruit::impl::InstallComponentFunctions<ComponentFunctions...>>;
269   (void)typename fruit::impl::meta::CheckIfError<Op>::type();
270 
271   std::tuple<ComponentFunctions...> component_functions_tuple{std::move(componentFunctions)...};
272 
273   return {{storage, std::move(component_functions_tuple)}};
274 }
275 
276 template <typename... Bindings>
277 template <typename... OtherComponentParams, typename... FormalArgs, typename... Args>
278 inline typename PartialComponent<Bindings...>::template PartialComponentWithReplacementInProgress<
279     fruit::Component<OtherComponentParams...>, FormalArgs...>
replace(fruit::Component<OtherComponentParams...> (* getReplacedComponent)(FormalArgs...),Args &&...args)280 PartialComponent<Bindings...>::replace(fruit::Component<OtherComponentParams...> (*getReplacedComponent)(FormalArgs...),
281                                        Args&&... args) {
282   using IntCollector = int[];
283   (void)IntCollector{0, fruit::impl::checkAcceptableComponentInstallArg<FormalArgs>()...};
284 
285   std::tuple<FormalArgs...> args_tuple{std::forward<Args>(args)...};
286 
287   return {{storage, getReplacedComponent, std::move(args_tuple)}};
288 }
289 
290 template <typename... Bindings>
291 template <typename OtherComponent, typename... GetReplacedComponentFormalArgs>
292 template <typename... GetReplacementComponentFormalArgs, typename... Args>
293 inline PartialComponent<fruit::impl::ReplaceComponent<OtherComponent(GetReplacedComponentFormalArgs...),
294                                                       OtherComponent(GetReplacementComponentFormalArgs...)>,
295                         Bindings...>
296 PartialComponent<Bindings...>::
with(OtherComponent (* getReplacementComponent)(GetReplacementComponentFormalArgs...),Args &&...args)297     PartialComponentWithReplacementInProgress<OtherComponent, GetReplacedComponentFormalArgs...>::with(
298         OtherComponent (*getReplacementComponent)(GetReplacementComponentFormalArgs...), Args&&... args) {
299   using IntCollector = int[];
300   (void)IntCollector{0, fruit::impl::checkAcceptableComponentInstallArg<GetReplacementComponentFormalArgs>()...};
301 
302   std::tuple<GetReplacementComponentFormalArgs...> args_tuple{std::forward<Args>(args)...};
303 
304   return {{storage, getReplacementComponent, std::move(args_tuple)}};
305 }
306 
307 } // namespace fruit
308 
309 #endif // FRUIT_COMPONENT_DEFN_H
310