Skip to content

Commit

Permalink
Implement AbslStringify for the Descriptor family of types.
Browse files Browse the repository at this point in the history
Implementing this method allows descriptors to be used in contexts that support
ABSL's formatting, most notably gunit's PrintToString and absl's StrFormat. The
implementations are done on the concrete descriptor type, which appears to be more
idiomatic for AbslStringify. Implementing them on pointers-to-descriptors would be
nicer for users who typically interact with pointers, but that would conflict with
AbslStringify's built-in support for pointers.

The implementation simply forwards to DebugString for simplicity.

PiperOrigin-RevId: 558854354
  • Loading branch information
pizzud authored and copybara-github committed Aug 21, 2023
1 parent a2b3470 commit 230232a
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/google/protobuf/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/optional.h"
Expand Down Expand Up @@ -347,6 +348,12 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
// include original user comments in output).
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const Descriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Returns true if this is a placeholder for an unknown type. This will
// only be the case if this descriptor comes from a DescriptorPool
// with AllowUnknownDependencies() set.
Expand Down Expand Up @@ -981,6 +988,12 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase {
// See Descriptor::DebugStringWithOptions().
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const FieldDescriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Helper method to get the CppType for a particular Type.
static CppType TypeToCppType(Type type);

Expand Down Expand Up @@ -1186,6 +1199,12 @@ class PROTOBUF_EXPORT OneofDescriptor : private internal::SymbolBase {
// See Descriptor::DebugStringWithOptions().
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const OneofDescriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Source Location ---------------------------------------------------

// Updates |*out_location| to the source location of the complete
Expand Down Expand Up @@ -1307,6 +1326,12 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase {
// See Descriptor::DebugStringWithOptions().
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const EnumDescriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Returns true if this is a placeholder for an unknown enum. This will
// only be the case if this descriptor comes from a DescriptorPool
// with AllowUnknownDependencies() set.
Expand Down Expand Up @@ -1500,6 +1525,12 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>,
// See Descriptor::DebugStringWithOptions().
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const EnumValueDescriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Source Location ---------------------------------------------------

// Updates |*out_location| to the source location of the complete
Expand Down Expand Up @@ -1597,6 +1628,12 @@ class PROTOBUF_EXPORT ServiceDescriptor : private internal::SymbolBase {
// See Descriptor::DebugStringWithOptions().
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const ServiceDescriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Source Location ---------------------------------------------------

// Updates |*out_location| to the source location of the complete
Expand Down Expand Up @@ -1698,6 +1735,12 @@ class PROTOBUF_EXPORT MethodDescriptor : private internal::SymbolBase {
// See Descriptor::DebugStringWithOptions().
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const MethodDescriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Source Location ---------------------------------------------------

// Updates |*out_location| to the source location of the complete
Expand Down Expand Up @@ -1913,6 +1956,12 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase {
// See Descriptor::DebugStringWithOptions().
std::string DebugStringWithOptions(const DebugStringOptions& options) const;

// Allows formatting with absl and gtest.
template <typename Sink>
friend void AbslStringify(Sink& sink, const FileDescriptor& d) {
absl::Format(&sink, "%s", d.DebugString());
}

// Returns true if this is a placeholder for an unknown file. This will
// only be the case if this descriptor comes from a DescriptorPool
// with AllowUnknownDependencies() set.
Expand Down
29 changes: 29 additions & 0 deletions src/google/protobuf/descriptor_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <cstdlib>
#include <limits>
#include <memory>
#include <string>
#include <tuple>
#include <vector>

Expand Down Expand Up @@ -83,6 +84,7 @@

using ::testing::AnyOf;
using ::testing::ElementsAre;
using ::testing::HasSubstr;
using ::testing::NotNull;

namespace google {
Expand Down Expand Up @@ -614,6 +616,13 @@ TEST_F(FileDescriptorTest, DebugStringRoundTrip) {
}
}

TEST_F(FileDescriptorTest, AbslStringifyWorks) {
std::string s = absl::StrFormat(
"%v",
*protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file());
EXPECT_THAT(s, HasSubstr("TestMessageWithCustomOptions"));
}

// ===================================================================

// Test simple flat messages and fields.
Expand Down Expand Up @@ -1209,6 +1218,12 @@ TEST_F(DescriptorTest, FieldEnumType) {
EXPECT_EQ(enum_, bar_->enum_type());
}

TEST_F(DescriptorTest, AbslStringifyWorks) {
EXPECT_THAT(absl::StrFormat("%v", *message_),
HasSubstr(message_->full_name()));
EXPECT_THAT(absl::StrFormat("%v", *foo_), HasSubstr(foo_->name()));
}


// ===================================================================

Expand Down Expand Up @@ -1302,6 +1317,10 @@ TEST_F(OneofDescriptorTest, FindByName) {
EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == nullptr);
}

TEST_F(OneofDescriptorTest, AbslStringifyWorks) {
EXPECT_THAT(absl::StrFormat("%v", *oneof_), HasSubstr(oneof_->name()));
}

// ===================================================================

class StylizedFieldNamesTest : public testing::Test {
Expand Down Expand Up @@ -1650,6 +1669,11 @@ TEST_F(EnumDescriptorTest, IsClosed) {
EXPECT_FALSE(enum3->is_closed());
}

TEST_F(EnumDescriptorTest, AbslStringifyWorks) {
EXPECT_THAT(absl::StrFormat("%v", *enum_), HasSubstr(enum_->full_name()));
EXPECT_THAT(absl::StrFormat("%v", *foo_), HasSubstr(foo_->name()));
}

// ===================================================================

// Test service descriptors.
Expand Down Expand Up @@ -1810,6 +1834,11 @@ TEST_F(ServiceDescriptorTest, MethodOutputType) {
EXPECT_EQ(bar_response_, bar_->output_type());
}

TEST_F(ServiceDescriptorTest, AbslStringifyWorks) {
EXPECT_THAT(absl::StrFormat("%v", *service_), HasSubstr(service_->name()));
EXPECT_THAT(absl::StrFormat("%v", *foo_), HasSubstr(foo_->name()));
}

// ===================================================================

// Test nested types.
Expand Down

0 comments on commit 230232a

Please sign in to comment.