Skip to content

Commit e13b8e9

Browse files
Prepare the code for migrating return types from const std::string& to
`absl::string_view`. Added temporary macro `PROTOBUF_TEMPORARY_ENABLE_STRING_VIEW_RETURN_TYPE` to turn on the new return type before the breaking change happens. It allows users to test and update their code ahead of time. PiperOrigin-RevId: 652517294
1 parent 8e60d9f commit e13b8e9

22 files changed

+268
-200
lines changed

conformance/binary_json_conformance_suite.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1810,7 +1810,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::
18101810
const std::string type_name =
18111811
UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type)));
18121812
const FieldDescriptor* field = GetFieldForType(type, true, Packed::kFalse);
1813-
std::string field_name = field->name();
1813+
const absl::string_view field_name = field->name();
18141814

18151815
std::string message_field =
18161816
absl::StrCat("\"", field_name, "\": [", field_value, "]");

src/google/protobuf/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,7 @@ cc_library(
11441144
"//src/google/protobuf/testing:file",
11451145
"@com_google_absl//absl/container:flat_hash_map",
11461146
"@com_google_absl//absl/log:absl_check",
1147+
"@com_google_absl//absl/strings",
11471148
"@com_google_absl//absl/time",
11481149
"@com_google_googletest//:gtest",
11491150
],

src/google/protobuf/descriptor.cc

Lines changed: 97 additions & 95 deletions
Large diffs are not rendered by default.

src/google/protobuf/descriptor.h

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ namespace internal {
194194
#define PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(t, expected)
195195
#endif
196196

197+
// `typedef` instead of `using` for SWIG
198+
#if defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE)
199+
typedef absl::string_view DescriptorStringView;
200+
#else
201+
typedef const std::string& DescriptorStringView;
202+
#endif
203+
197204
class FlatAllocator;
198205

199206
class PROTOBUF_EXPORT LazyDescriptor {
@@ -286,6 +293,9 @@ PROTOBUF_EXPORT absl::string_view ShortEditionName(Edition edition);
286293

287294
bool IsEnumFullySequential(const EnumDescriptor* enum_desc);
288295

296+
const std::string& DefaultValueStringAsString(const FieldDescriptor* field);
297+
const std::string& NameOfEnumAsString(const EnumValueDescriptor* descriptor);
298+
289299
} // namespace internal
290300

291301
// Provide an Abseil formatter for edition names.
@@ -308,14 +318,14 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
308318
#endif
309319

310320
// The name of the message type, not including its scope.
311-
const std::string& name() const;
321+
internal::DescriptorStringView name() const;
312322

313323
// The fully-qualified name of the message type, scope delimited by
314324
// periods. For example, message type "Foo" which is declared in package
315325
// "bar" has full name "bar.Foo". If a type "Baz" is nested within
316326
// Foo, Baz's full_name is "bar.Foo.Baz". To get only the part that
317327
// comes after the last '.', use name().
318-
const std::string& full_name() const;
328+
internal::DescriptorStringView full_name() const;
319329

320330
// Index of this descriptor within the file or containing type's message
321331
// type array.
@@ -493,10 +503,12 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
493503
const ExtensionRangeOptions& options() const { return *options_; }
494504

495505
// Returns the name of the containing type.
496-
const std::string& name() const { return containing_type_->name(); }
506+
internal::DescriptorStringView name() const {
507+
return containing_type_->name();
508+
}
497509

498510
// Returns the full name of the containing type.
499-
const std::string& full_name() const {
511+
internal::DescriptorStringView full_name() const {
500512
return containing_type_->full_name();
501513
}
502514

@@ -615,7 +627,7 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
615627
int reserved_name_count() const;
616628

617629
// Gets a reserved name by index, where 0 <= index < reserved_name_count().
618-
const std::string& reserved_name(int index) const;
630+
internal::DescriptorStringView reserved_name(int index) const;
619631

620632
// Returns true if the field name is reserved.
621633
bool IsReservedName(absl::string_view name) const;
@@ -827,9 +839,13 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
827839
// Users may not declare fields that use reserved numbers.
828840
static const int kLastReservedNumber = 19999;
829841

830-
const std::string& name() const; // Name of this field within the message.
831-
const std::string& full_name() const; // Fully-qualified name of the field.
832-
const std::string& json_name() const; // JSON name of this field.
842+
// Name of this field within the message.
843+
internal::DescriptorStringView name() const;
844+
// Fully-qualified name of the field.
845+
internal::DescriptorStringView full_name() const;
846+
// JSON name of this field.
847+
internal::DescriptorStringView json_name() const;
848+
833849
const FileDescriptor* file() const; // File in which this field was defined.
834850
bool is_extension() const; // Is this an extension field?
835851
int number() const; // Declared tag number.
@@ -840,7 +856,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
840856
// field names should be lowercased anyway according to the protobuf style
841857
// guide, so this only makes a difference when dealing with old .proto files
842858
// which do not follow the guide.)
843-
const std::string& lowercase_name() const;
859+
internal::DescriptorStringView lowercase_name() const;
844860

845861
// Same as name() except converted to camel-case. In this conversion, any
846862
// time an underscore appears in the name, it is removed and the next
@@ -851,7 +867,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
851867
// fooBar -> fooBar
852868
// This (and especially the FindFieldByCamelcaseName() method) can be useful
853869
// when parsing formats which prefer to use camel-case naming style.
854-
const std::string& camelcase_name() const;
870+
internal::DescriptorStringView camelcase_name() const;
855871

856872
Type type() const; // Declared type of this field.
857873
const char* type_name() const; // Name of the declared type.
@@ -947,7 +963,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
947963
const EnumValueDescriptor* default_value_enum() const;
948964
// Get the field default value if cpp_type() == CPPTYPE_STRING. If no
949965
// explicit default was defined, the default is the empty string.
950-
const std::string& default_value_string() const;
966+
internal::DescriptorStringView default_value_string() const;
951967

952968
// The Descriptor for the message of which this is a field. For extensions,
953969
// this is the extended type. Never nullptr.
@@ -1025,7 +1041,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
10251041
// its printable name) can be accomplished with
10261042
// message->file()->pool()->FindExtensionByPrintableName(message, name)
10271043
// where the extension extends "message".
1028-
const std::string& PrintableNameForExtension() const;
1044+
internal::DescriptorStringView PrintableNameForExtension() const;
10291045

10301046
// Source Location ---------------------------------------------------
10311047

@@ -1043,6 +1059,8 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase,
10431059
friend class compiler::cpp::Formatter;
10441060
friend class Reflection;
10451061
friend class FieldDescriptorLegacy;
1062+
friend const std::string& internal::DefaultValueStringAsString(
1063+
const FieldDescriptor* field);
10461064

10471065
// Returns true if this field was syntactically written with "optional" in the
10481066
// .proto file. Excludes singular proto3 fields that do not have a label.
@@ -1176,8 +1194,10 @@ class PROTOBUF_EXPORT OneofDescriptor : private internal::SymbolBase {
11761194
OneofDescriptor& operator=(const OneofDescriptor&) = delete;
11771195
#endif
11781196

1179-
const std::string& name() const; // Name of this oneof.
1180-
const std::string& full_name() const; // Fully-qualified name of the oneof.
1197+
// Name of this oneof.
1198+
internal::DescriptorStringView name() const;
1199+
// Fully-qualified name of the oneof.
1200+
internal::DescriptorStringView full_name() const;
11811201

11821202
// Index of this oneof within the message's oneof array.
11831203
int index() const;
@@ -1282,10 +1302,10 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase {
12821302
#endif
12831303

12841304
// The name of this enum type in the containing scope.
1285-
const std::string& name() const;
1305+
internal::DescriptorStringView name() const;
12861306

12871307
// The fully-qualified name of the enum type, scope delimited by periods.
1288-
const std::string& full_name() const;
1308+
internal::DescriptorStringView full_name() const;
12891309

12901310
// Index of this enum within the file or containing message's enum array.
12911311
int index() const;
@@ -1381,7 +1401,7 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase {
13811401
int reserved_name_count() const;
13821402

13831403
// Gets a reserved name by index, where 0 <= index < reserved_name_count().
1384-
const std::string& reserved_name(int index) const;
1404+
internal::DescriptorStringView reserved_name(int index) const;
13851405

13861406
// Returns true if the field name is reserved.
13871407
bool IsReservedName(absl::string_view name) const;
@@ -1494,7 +1514,7 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>,
14941514
EnumValueDescriptor& operator=(const EnumValueDescriptor&) = delete;
14951515
#endif
14961516

1497-
const std::string& name() const; // Name of this enum constant.
1517+
internal::DescriptorStringView name() const; // Name of this enum constant.
14981518
int index() const; // Index within the enums's Descriptor.
14991519
int number() const; // Numeric value of this enum constant.
15001520

@@ -1503,7 +1523,7 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>,
15031523
// "google.protobuf.FieldDescriptorProto.TYPE_INT32", NOT
15041524
// "google.protobuf.FieldDescriptorProto.Type.TYPE_INT32". This is to conform
15051525
// with C++ scoping rules for enums.
1506-
const std::string& full_name() const;
1526+
internal::DescriptorStringView full_name() const;
15071527

15081528
// The .proto file in which this value was defined. Never nullptr.
15091529
const FileDescriptor* file() const;
@@ -1545,6 +1565,8 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>,
15451565
// Allows access to GetLocationPath for annotations.
15461566
friend class io::Printer;
15471567
friend class compiler::cpp::Formatter;
1568+
friend const std::string& internal::NameOfEnumAsString(
1569+
const EnumValueDescriptor* descriptor);
15481570

15491571
// Get the merged features that apply to this enum value. These are specified
15501572
// in the .proto file through the feature options in the message definition.
@@ -1595,9 +1617,9 @@ class PROTOBUF_EXPORT ServiceDescriptor : private internal::SymbolBase {
15951617
#endif
15961618

15971619
// The name of the service, not including its containing scope.
1598-
const std::string& name() const;
1620+
internal::DescriptorStringView name() const;
15991621
// The fully-qualified name of the service, scope delimited by periods.
1600-
const std::string& full_name() const;
1622+
internal::DescriptorStringView full_name() const;
16011623
// Index of this service within the file's services array.
16021624
int index() const;
16031625

@@ -1699,9 +1721,9 @@ class PROTOBUF_EXPORT MethodDescriptor : private internal::SymbolBase {
16991721
#endif
17001722

17011723
// Name of this method, not including containing scope.
1702-
const std::string& name() const;
1724+
internal::DescriptorStringView name() const;
17031725
// The fully-qualified name of the method, scope delimited by periods.
1704-
const std::string& full_name() const;
1726+
internal::DescriptorStringView full_name() const;
17051727
// Index within the service's Descriptor.
17061728
int index() const;
17071729

@@ -1807,10 +1829,10 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase {
18071829

18081830
// The filename, relative to the source tree.
18091831
// e.g. "foo/bar/baz.proto"
1810-
const std::string& name() const;
1832+
internal::DescriptorStringView name() const;
18111833

18121834
// The package, e.g. "google.protobuf.compiler".
1813-
const std::string& package() const;
1835+
internal::DescriptorStringView package() const;
18141836

18151837
// The DescriptorPool in which this FileDescriptor and all its contents were
18161838
// allocated. Never nullptr.
@@ -2472,13 +2494,19 @@ class PROTOBUF_EXPORT DescriptorPool {
24722494
inline TYPE CLASS::FIELD() const { return FIELD##_; }
24732495

24742496
// Strings fields are stored as pointers but returned as const references.
2475-
#define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \
2476-
inline const std::string& CLASS::FIELD() const { return *FIELD##_; }
2497+
#define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \
2498+
inline internal::DescriptorStringView CLASS::FIELD() const { \
2499+
return *FIELD##_; \
2500+
}
24772501

24782502
// Name and full name are stored in a single array to save space.
2479-
#define PROTOBUF_DEFINE_NAME_ACCESSOR(CLASS) \
2480-
inline const std::string& CLASS::name() const { return all_names_[0]; } \
2481-
inline const std::string& CLASS::full_name() const { return all_names_[1]; }
2503+
#define PROTOBUF_DEFINE_NAME_ACCESSOR(CLASS) \
2504+
inline internal::DescriptorStringView CLASS::name() const { \
2505+
return all_names_[0]; \
2506+
} \
2507+
inline internal::DescriptorStringView CLASS::full_name() const { \
2508+
return all_names_[1]; \
2509+
}
24822510

24832511
// Arrays take an index parameter, obviously.
24842512
#define PROTOBUF_DEFINE_ARRAY_ACCESSOR(CLASS, FIELD, TYPE) \
@@ -2627,7 +2655,8 @@ inline bool Descriptor::IsReservedName(absl::string_view name) const {
26272655

26282656
// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually
26292657
// an array of pointers rather than the usual array of objects.
2630-
inline const std::string& Descriptor::reserved_name(int index) const {
2658+
inline internal::DescriptorStringView Descriptor::reserved_name(
2659+
int index) const {
26312660
return *reserved_names_[index];
26322661
}
26332662

@@ -2646,19 +2675,20 @@ inline bool EnumDescriptor::IsReservedName(absl::string_view name) const {
26462675

26472676
// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually
26482677
// an array of pointers rather than the usual array of objects.
2649-
inline const std::string& EnumDescriptor::reserved_name(int index) const {
2678+
inline internal::DescriptorStringView EnumDescriptor::reserved_name(
2679+
int index) const {
26502680
return *reserved_names_[index];
26512681
}
26522682

2653-
inline const std::string& FieldDescriptor::lowercase_name() const {
2683+
inline internal::DescriptorStringView FieldDescriptor::lowercase_name() const {
26542684
return all_names_[lowercase_name_index_];
26552685
}
26562686

2657-
inline const std::string& FieldDescriptor::camelcase_name() const {
2687+
inline internal::DescriptorStringView FieldDescriptor::camelcase_name() const {
26582688
return all_names_[camelcase_name_index_];
26592689
}
26602690

2661-
inline const std::string& FieldDescriptor::json_name() const {
2691+
inline internal::DescriptorStringView FieldDescriptor::json_name() const {
26622692
return all_names_[json_name_index_];
26632693
}
26642694

@@ -2822,6 +2852,16 @@ inline const FileDescriptor* FileDescriptor::weak_dependency(int index) const {
28222852

28232853
namespace internal {
28242854

2855+
inline const std::string& DefaultValueStringAsString(
2856+
const FieldDescriptor* field) {
2857+
return *field->default_value_string_;
2858+
}
2859+
2860+
inline const std::string& NameOfEnumAsString(
2861+
const EnumValueDescriptor* descriptor) {
2862+
return descriptor->all_names_[0];
2863+
}
2864+
28252865
inline bool IsEnumFullySequential(const EnumDescriptor* enum_desc) {
28262866
return enum_desc->sequential_value_limit_ == enum_desc->value_count() - 1;
28272867
}

src/google/protobuf/descriptor_unittest.cc

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -570,15 +570,15 @@ TEST_F(FileDescriptorTest, CopyHeadingTo) {
570570
}
571571

572572
void ExtractDebugString(
573-
const FileDescriptor* file, absl::flat_hash_set<std::string>* visited,
574-
std::vector<std::pair<std::string, std::string>>* debug_strings) {
573+
const FileDescriptor* file, absl::flat_hash_set<absl::string_view>* visited,
574+
std::vector<std::pair<absl::string_view, std::string>>* debug_strings) {
575575
if (!visited->insert(file->name()).second) {
576576
return;
577577
}
578578
for (int i = 0; i < file->dependency_count(); ++i) {
579579
ExtractDebugString(file->dependency(i), visited, debug_strings);
580580
}
581-
debug_strings->push_back(std::make_pair(file->name(), file->DebugString()));
581+
debug_strings->push_back({file->name(), file->DebugString()});
582582
}
583583

584584
class SimpleErrorCollector : public io::ErrorCollector {
@@ -596,8 +596,8 @@ class SimpleErrorCollector : public io::ErrorCollector {
596596
// Test that the result of FileDescriptor::DebugString() can be used to create
597597
// the original descriptors.
598598
TEST_F(FileDescriptorTest, DebugStringRoundTrip) {
599-
absl::flat_hash_set<std::string> visited;
600-
std::vector<std::pair<std::string, std::string>> debug_strings;
599+
absl::flat_hash_set<absl::string_view> visited;
600+
std::vector<std::pair<absl::string_view, std::string>> debug_strings;
601601
ExtractDebugString(protobuf_unittest::TestAllTypes::descriptor()->file(),
602602
&visited, &debug_strings);
603603
ExtractDebugString(
@@ -609,7 +609,7 @@ TEST_F(FileDescriptorTest, DebugStringRoundTrip) {
609609

610610
DescriptorPool pool;
611611
for (size_t i = 0; i < debug_strings.size(); ++i) {
612-
const std::string& name = debug_strings[i].first;
612+
const absl::string_view name = debug_strings[i].first;
613613
const std::string& content = debug_strings[i].second;
614614
io::ArrayInputStream input_stream(content.data(), content.size());
615615
SimpleErrorCollector error_collector;
@@ -850,16 +850,17 @@ TEST_F(DescriptorTest, ContainingType) {
850850

851851
TEST_F(DescriptorTest, FieldNamesDedup) {
852852
const auto collect_unique_names = [](const FieldDescriptor* field) {
853-
absl::btree_set<std::string> names{field->name(), field->lowercase_name(),
854-
field->camelcase_name(),
855-
field->json_name()};
853+
absl::btree_set<absl::string_view> names{
854+
field->name(), field->lowercase_name(), field->camelcase_name(),
855+
field->json_name()};
856856
// Verify that we have the same number of string objects as we have string
857857
// values. That is, duplicate names use the same std::string object.
858858
// This is for memory efficiency.
859-
EXPECT_EQ(names.size(), (absl::flat_hash_set<const std::string*>{
860-
&field->name(), &field->lowercase_name(),
861-
&field->camelcase_name(), &field->json_name()}
862-
.size()))
859+
EXPECT_EQ(names.size(),
860+
(absl::flat_hash_set<const void*>{
861+
field->name().data(), field->lowercase_name().data(),
862+
field->camelcase_name().data(), field->json_name().data()}
863+
.size()))
863864
<< testing::PrintToString(names);
864865
return names;
865866
};

0 commit comments

Comments
 (0)