// Copyright 2023 gRPC authors. // // 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 GRPC_SRC_CORE_LIB_PROMISE_SWITCH_H #define GRPC_SRC_CORE_LIB_PROMISE_SWITCH_H #include #include #include #include "src/core/lib/promise/detail/promise_factory.h" #include "src/core/lib/promise/detail/promise_variant.h" #include "src/core/lib/promise/if.h" #include "src/core/util/crash.h" namespace grpc_core { namespace promise_detail { template struct Case { using Factory = OncePromiseFactory; explicit Case(F f) : factory(std::move(f)) {} Factory factory; static bool Matches(D value) { return value == discriminator; } }; template struct Default { using Factory = OncePromiseFactory; explicit Default(F f) : factory(std::move(f)) {} Factory factory; }; template Promise ConstructSwitchPromise(D, Default& def) { return def.factory.Make(); } template Promise ConstructSwitchPromise(D discriminator, Case& c, OtherCases&... cs) { if (Case::Matches(discriminator)) return c.factory.Make(); return ConstructSwitchPromise(discriminator, cs...); } template auto SwitchImpl(D discriminator, Cases&... cases) { using Promise = absl::variant; return PromiseVariant( ConstructSwitchPromise(discriminator, cases...)); } } // namespace promise_detail // TODO(ctiller): when we have C++17, make this // template . // (this way we don't need to list the type on /every/ case) template auto Case(PromiseFactory f) { return promise_detail::Case{std::move(f)}; } template auto Default(PromiseFactory f) { return promise_detail::Default{std::move(f)}; } // Given a list of cases that result in promise factories, return a single // promise chosen by the discriminator (the first argument of this function). // e.g.: // Switch(1, Case<1>([] { return 43; }), Case<2>([] { return 44; })) // resolves to 43. // TODO(ctiller): consider writing a code-generator like we do for seq/join // so that this lowers into a C switch statement. template auto Switch(D discriminator, C... cases) { return promise_detail::SwitchImpl(discriminator, cases...); } } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_PROMISE_SWITCH_H