• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_SRC_CORE_LIB_PROMISE_MATCH_PROMISE_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_MATCH_PROMISE_H
17 
18 #include "absl/types/variant.h"
19 #include "src/core/lib/promise/detail/promise_factory.h"
20 #include "src/core/lib/promise/detail/promise_like.h"
21 #include "src/core/lib/promise/detail/promise_variant.h"
22 #include "src/core/util/overload.h"
23 
24 namespace grpc_core {
25 
26 namespace promise_detail {
27 
28 // This types job is to visit a supplied variant, and apply a mapping
29 // Constructor from input types to promises, returning a variant full of
30 // promises.
31 template <typename Constructor, typename... Ts>
32 struct ConstructPromiseVariantVisitor {
33   // Factory functions supplied to the top level `Match` object, wrapped by
34   // OverloadType to become overloaded members.
35   Constructor constructor;
36 
37   // Helper function... only callable once.
38   // Given a value, construct a Promise Factory that accepts that value type,
39   // and uses the constructor type above to map from that type to a promise
40   // returned by the factory.
41   // We use the Promise Factory infrastructure to deal with all the common
42   // variants of factory signatures that we've found to be convenient.
43   template <typename T>
CallConstructorThenFactoryConstructPromiseVariantVisitor44   auto CallConstructorThenFactory(T x) {
45     OncePromiseFactory<T, Constructor> factory(std::move(constructor));
46     return factory.Make(std::move(x));
47   }
48 
49   // Polling operator.
50   // Given a visited type T, construct a Promise Factory, use it, and then cast
51   // the result into a variant type that covers ALL of the possible return types
52   // given the input types listed in Ts...
53   template <typename T>
54   auto operator()(T x) -> absl::variant<promise_detail::PromiseLike<
55       decltype(CallConstructorThenFactory(std::declval<Ts>()))>...> {
56     return CallConstructorThenFactory(std::move(x));
57   }
58 };
59 
60 }  // namespace promise_detail
61 
62 // Match for promises
63 // Like the Match function takes a variant of some set of types,
64 // and a set of functions - one per variant type.
65 // We use these functions as Promise Factories, and return a Promise that can be
66 // polled selected by the type that was in the variant.
67 template <typename... Fs, typename... Ts>
MatchPromise(absl::variant<Ts...> value,Fs...fs)68 auto MatchPromise(absl::variant<Ts...> value, Fs... fs) {
69   // Construct a variant of promises using the factory functions fs, selected by
70   // the type held by value.
71   auto body = absl::visit(
72       promise_detail::ConstructPromiseVariantVisitor<OverloadType<Fs...>,
73                                                      Ts...>{
74           OverloadType<Fs...>(std::move(fs)...)},
75       std::move(value));
76   // Wrap that in a PromiseVariant that provides the promise API on the wrapped
77   // variant.
78   return promise_detail::PromiseVariant<decltype(body)>(std::move(body));
79 }
80 
81 }  // namespace grpc_core
82 
83 #endif  // GRPC_SRC_CORE_LIB_PROMISE_MATCH_PROMISE_H
84