• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #ifndef THIRD_PARTY_UPB_UPB_GENERATOR_C_NAMES_H_
9 #define THIRD_PARTY_UPB_UPB_GENERATOR_C_NAMES_H_
10 
11 #include <string>
12 
13 #include "absl/container/flat_hash_map.h"
14 #include "absl/strings/string_view.h"
15 
16 namespace upb {
17 namespace generator {
18 
19 // Note: these names are not currently exported, in hopes that no code
20 // generators outside of the protobuf repo will ever use the generated C API.
21 
22 // Maps: foo/bar/baz.proto -> foo/bar/baz.upb.h
23 std::string CApiHeaderFilename(absl::string_view proto_filename);
24 
25 // The foo.upb.h file defines far more symbols than we currently enumerate here.
26 // We do the bare minimum by by defining the type name for messages and enums,
27 // which also forms the symbol prefix for associated functions.
28 //
29 //   typedef struct { /* ... */ } <MessageType>;
30 //   typedef enum { <EnumValue> = X, ... } <EnumType>;
31 //
32 // Oneofs and extensions have a base name that forms the prefix for associated
33 // functions.
34 
35 std::string CApiMessageType(absl::string_view full_name);
36 std::string CApiEnumType(absl::string_view full_name);
37 std::string CApiEnumValueSymbol(absl::string_view full_name);
38 std::string CApiExtensionIdentBase(absl::string_view full_name);
39 std::string CApiOneofIdentBase(absl::string_view full_name);
40 
41 // Name mangling for individual fields. NameMangler maps each field name to a
42 // mangled name, which tries to avoid collisions with other field accessors.
43 //
44 // For example, a field named "clear_foo" might be renamed to "clear_foo_" if
45 // there is a field named "foo" in the same message.
46 //
47 // This API would be more principled if it generated a full symbol name for each
48 // generated API function, eg.
49 //   mangler.GetSetter("clear_foo") -> "mypkg_MyMessage_set_clear_foo_"
50 //   mangler.GetHazzer("clear_foo") -> "mypkg_MyMessage_has_clear_foo_"
51 //
52 // But that would be a larger and more complicated API. In the long run, we
53 // probably don't want to have other code generators wrapping these APIs, so
54 // it's probably not worth designing a fully principled API.
55 
56 enum FieldClass {
57   kStringField = 1 << 0,
58   kContainerField = 1 << 1,
59   kOtherField = 1 << 2,
60 };
61 
62 class NameMangler {
63  public:
64   explicit NameMangler(
65       const absl::flat_hash_map<std::string, FieldClass>& fields);
66 
ResolveFieldName(absl::string_view name)67   std::string ResolveFieldName(absl::string_view name) const {
68     auto it = names_.find(name);
69     return it == names_.end() ? std::string(name) : it->second;
70   }
71 
72  private:
73   // Maps field_name -> mangled_name.  If a field name is not in the map, it
74   // is not mangled.
75   absl::flat_hash_map<std::string, std::string> names_;
76 };
77 
78 // Here we provide functions for building field lists from both C++ and upb
79 // reflection.  They are templated so as to not actually introduce dependencies
80 // on either C++ or upb.
81 
82 template <class T>
GetCppFields(const T * descriptor)83 absl::flat_hash_map<std::string, FieldClass> GetCppFields(const T* descriptor) {
84   absl::flat_hash_map<std::string, FieldClass> fields;
85   for (int i = 0; i < descriptor->field_count(); ++i) {
86     const auto* field = descriptor->field(i);
87     if (field->is_repeated() || field->is_map()) {
88       fields.emplace(field->name(), kContainerField);
89     } else if (field->cpp_type() == field->CPPTYPE_STRING) {
90       fields.emplace(field->name(), kStringField);
91     } else {
92       fields.emplace(field->name(), kOtherField);
93     }
94   }
95   return fields;
96 }
97 
98 template <class T>
GetUpbFields(const T & msg_def)99 absl::flat_hash_map<std::string, FieldClass> GetUpbFields(const T& msg_def) {
100   absl::flat_hash_map<std::string, FieldClass> fields;
101   for (const auto field : msg_def.fields()) {
102     if (field.IsSequence() || field.IsMap()) {
103       fields.emplace(field.name(), kContainerField);
104     } else if (field.ctype() == decltype(field)::CType::kUpb_CType_String) {
105       fields.emplace(field.name(), kStringField);
106     } else {
107       fields.emplace(field.name(), kOtherField);
108     }
109   }
110   return fields;
111 }
112 
113 ABSL_CONST_INIT const absl::string_view kRepeatedFieldArrayGetterPostfix =
114     "upb_array";
115 ABSL_CONST_INIT const absl::string_view
116     kRepeatedFieldMutableArrayGetterPostfix = "mutable_upb_array";
117 
118 ABSL_CONST_INIT const absl::string_view kMapGetterPostfix = "upb_map";
119 ABSL_CONST_INIT const absl::string_view kMutableMapGetterPostfix =
120     "mutable_upb_map";
121 
122 }  // namespace generator
123 }  // namespace upb
124 
125 #endif  // THIRD_PARTY_UPB_UPB_GENERATOR_C_NAMES_H_
126