/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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. */ #pragma once #include #include namespace apache { namespace thrift { namespace detail { template constexpr std::size_t countTypeInUnion() { std::size_t count = 0; op::for_each_ordinal([&](auto id) { count += std::is_same_v, Type>; }); return count; } template void findTypeInUnion(V& variant, F f) { using Union = std::remove_cvref_t; using Type = std::remove_cvref_t; static_assert(is_thrift_union_v); static_assert(countTypeInUnion() == 1); op::for_each_ordinal([&](auto id) { using Id = decltype(id); if constexpr (std::is_same_v, Type>) { f(op::get(variant)); } }); } } // namespace detail /** * Gets a pointer to the Thrift union's member for the given type. * * If the desired field is not the one currently set in the union, returns * `nullptr`. * * Example: * * // Foo.thrift * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * // foo.cpp * #include "project_dir/gen-cpp2/Foo_types.h" * * MyUnion u; * u.a_ref() = 10; * * // yields a pointer to field `a` * std::cout << variant_try_get(u); * * // yields `nullptr` * std::cout << variant_try_get(u); */ template folly::like_t* variant_try_get(V& variant) { folly::like_t* ret = nullptr; detail::findTypeInUnion(variant, [&](auto p) { if (p) { ret = &*p; } }); return ret; } /** * Sets the Thrift union's member for the given type with the provided value. * * Example: * * // Foo.thrift * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * // foo.cpp * #include "project_dir/gen-cpp2/Foo_types.h" * * MyUnion u; * * // sets the field `a` to the value `10`. * variant_set(u, 10); * * std::cout << *u.a_ref(); */ template void variant_set(V& variant, T&& value) { detail::findTypeInUnion( variant, [&](auto p) { p = std::forward(value); }); } } // namespace thrift } // namespace apache