/* * 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 namespace apache { namespace thrift { namespace merge_into_detail { template struct merge { using impl = merge_impl; // regular static void go(const T& src, T& dst) { impl::template go(src, dst); } static void go(T&& src, T& dst) { impl::template go(std::move(src), dst); } static void go( optional_boxed_field_ref&> src, optional_boxed_field_ref&> dst) { if (!dst) { dst.copy_from(src); } else if (src) { go(*src, *dst); } } static void go( optional_boxed_field_ref&&> src, optional_boxed_field_ref&> dst) { if (!dst) { dst.move_from(src); } else if (src) { go(std::move(*src), *dst); src.reset(); } } static void go(const std::unique_ptr& src, std::unique_ptr& dst) { dst = !src ? nullptr : std::make_unique(*src); } static void go(std::unique_ptr&& src, std::unique_ptr& dst) { dst = std::move(src); } static void go(const std::shared_ptr& src, std::shared_ptr& dst) { dst = src; } static void go(std::shared_ptr&& src, std::shared_ptr& dst) { dst = std::move(src); } static void go( const std::shared_ptr& src, std::shared_ptr& dst) { dst = src; } static void go( std::shared_ptr&& src, std::shared_ptr& dst) { dst = std::move(src); } }; template struct merge_impl { template static void go(const T& src, T& dst) { dst = src; } template static void go(T&& src, T& dst) { dst = std::move(src); } }; template <> struct merge_impl { template struct deref { using type = T; }; template struct deref> : deref::element_type> {}; template struct deref> : deref {}; template struct deref> : deref {}; template struct deref> : deref {}; template struct visitor { template using Src = fatal::conditional; template void operator()( fatal::indexed, Src& src, T& dst) const { using mgetter = typename MemberInfo::getter; using mclass = typename MemberInfo::type_class; using msrc = fatal::conditional&&, const Src&>; using mtype = folly::remove_cvref_t(src)))>; using merge_field = merge::type, mclass>; using mref = fatal::conditional; if (MemberInfo::optional::value == optionality::optional && !MemberInfo::is_set(src)) { return; } MemberInfo::mark_set(dst, true); merge_field::go( static_cast(mgetter{}(static_cast(src))), mgetter{}(dst)); } }; template static void go(const T& src, T& dst) { using members = typename reflect_struct::members; fatal::foreach(visitor(), src, dst); } template static void go(T&& src, T& dst) { using members = typename reflect_struct::members; fatal::foreach(visitor(), src, dst); } }; template struct merge_impl> { template static void go(const T& src, T& dst) { dst.reserve(dst.size() + src.size()); std::copy(src.cbegin(), src.cend(), std::back_inserter(dst)); } template static void go(T&& src, T& dst) { dst.reserve(dst.size() + src.size()); std::move(src.begin(), src.end(), std::back_inserter(dst)); } }; template struct merge_impl> { template static void go(const T& src, T& dst) { std::copy(src.cbegin(), src.cend(), std::inserter(dst, dst.end())); } template static void go(T&& src, T& dst) { std::move(src.begin(), src.end(), std::inserter(dst, dst.end())); } }; template struct merge_impl> { template static void go(const T& src, T& dst) { using M = typename T::mapped_type; for (const auto& kv : src) { merge::go(kv.second, dst[kv.first]); } } template static void go(T&& src, T& dst) { using M = typename T::mapped_type; for (auto& kv : src) { merge::go(std::move(kv.second), dst[kv.first]); } } }; } // namespace merge_into_detail } // namespace thrift } // namespace apache namespace apache { namespace thrift { template void merge_into(T&& src, merge_into_detail::remove_const_reference& dst) { constexpr auto c = std::is_const::value; constexpr auto r = std::is_rvalue_reference::value; using D = typename merge_into_detail::remove_const_reference; using W = fatal::conditional; using TC = type_class_of_thrift_class_t>; static_assert(!std::is_void_v, "merge_into: not a structure type"); merge_into_detail::merge::go(static_cast(src), dst); } } // namespace thrift } // namespace apache