/* * 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. */ #ifndef THRIFT_FATAL_PRETTY_PRINT_INL_POST_H_ #define THRIFT_FATAL_PRETTY_PRINT_INL_POST_H_ 1 #include #include #include #include #include namespace apache { namespace thrift { namespace detail { /** * Pretty print specialization for enumerations. * * @author: Marcelo Juchem */ template <> struct pretty_print_impl { template static void print(OutputStream& out, T const& what) { out << fatal::enum_to_string(what, nullptr); } }; /** * Pretty print specialization for lists. * * @author: Marcelo Juchem */ template struct pretty_print_impl> { template static void print(OutputStream& out, T const& what) { out << "["; if (!what.empty()) { out.newline(); const auto size = what.size(); std::size_t index = 0; for (const auto& i : what) { auto scope = out.start_scope(); scope << index << ": "; pretty_print_impl::print(scope, i); if (++index < size) { scope << ','; } scope.newline(); } } out << ']'; } }; /** * Pretty print specialization for maps. * * @author: Marcelo Juchem */ template struct pretty_print_impl> { template static void print(OutputStream& out, T const& what) { out << "{"; if (!what.empty()) { out.newline(); const auto size = what.size(); std::size_t index = 0; for (const auto& i : what) { auto scope = out.start_scope(); pretty_print_impl::print(scope, i.first); scope << ": "; pretty_print_impl::print(scope, i.second); if (++index < size) { scope << ','; } scope.newline(); } } out << '}'; } }; /** * Pretty print specialization for sets. * * @author: Marcelo Juchem */ template struct pretty_print_impl> { template static void print(OutputStream& out, T const& what) { out << "{"; if (!what.empty()) { out.newline(); const auto size = what.size(); std::size_t index = 0; for (const auto& i : what) { auto scope = out.start_scope(); pretty_print_impl::print(scope, i); if (++index < size) { scope << ','; } scope.newline(); } } out << '}'; } }; /** * Thrift structures and unions may contain members that are wrapped in smart * pointers. This class helps decode those. */ struct pretty_print_structure_with_pointers { protected: template static void recurse_into(OutputStream& out, T const& member) { pretty_print_impl::print(out, member); } template static void recurse_into_ptr(OutputStream& out, T const* pMember) { if (!pMember) { out << "null"; return; } recurse_into(out, *pMember); } template static void recurse_into( OutputStream& out, optional_boxed_field_ref&> pMember) { return recurse_into_ptr(out, pMember ? &*pMember : nullptr); } template static void recurse_into( OutputStream& out, const std::shared_ptr& pMember) { return recurse_into_ptr(out, pMember.get()); } template static void recurse_into( OutputStream& out, const std::unique_ptr& pMember) { return recurse_into_ptr(out, pMember.get()); } }; /** * Pretty print specialization for variants (Thrift unions). * * @author: Marcelo Juchem */ template <> struct pretty_print_impl : pretty_print_structure_with_pointers { template static void print(OutputStream& out, T const& what) { using descriptors = typename fatal::variant_traits::descriptors; out << "{"; using key = fatal::get_type::id; fatal::scalar_search(what.getType(), [&](auto indexed) { using descriptor = decltype(fatal::tag_type(indexed)); auto scope = out.start_scope(); scope.newline(); scope << fatal::enum_to_string(what.getType(), nullptr) << ": "; recurse_into( scope, typename descriptor::getter()(what)); scope.newline(); }); out << '}'; } }; /* * Pretty print specialization for structures. * * @author: Marcelo Juchem */ template <> struct pretty_print_impl : pretty_print_structure_with_pointers { template static void print(OutputStream& out, T const& what) { out << "{"; out.newline(); using info = reflect_struct; fatal::foreach([&](auto indexed) { constexpr auto size = fatal::size::value; using member = decltype(fatal::tag_type(indexed)); if (member::optional::value == optionality::optional && !member::is_set(what)) { return; } auto const index = fatal::tag_index(indexed); auto scope = out.start_scope(); scope << fatal::z_data() << ": "; recurse_into( scope, typename member::getter{}(what)); if (index + 1 < size) { scope << ','; } scope.newline(); }); out << '}'; } }; /** * Pretty print specialization for strings. * * @author: Marcelo Juchem */ template <> struct pretty_print_impl { template static void print(OutputStream& out, T const& what) { out << '"' << folly::cEscape(what) << '"'; } }; template <> struct pretty_print_impl { template static void print(OutputStream& out, T const& what) { out << R"("0x)" << folly::hexlify(what) << R"(")"; } template static void print(OutputStream& out, folly::IOBuf const& what) { return print(out, what.to()); } template static void print( OutputStream& out, std::unique_ptr const& what) { if (what) { return print(out, what->to()); } } }; /** * Pretty print fallback specialization. * * @author: Marcelo Juchem */ template struct pretty_print_impl { template static void print(OutputStream& out, T const& what) { out << what; } template static void print(OutputStream& out, const bool what) { out << (what ? "true" : "false"); } }; } // namespace detail } // namespace thrift } // namespace apache #endif // THRIFT_FATAL_PRETTY_PRINT_INL_POST_H_