• 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 GOOGLE_PROTOBUF_COMPILER_RUST_NAMING_H__
9 #define GOOGLE_PROTOBUF_COMPILER_RUST_NAMING_H__
10 
11 #include <array>
12 #include <string>
13 
14 #include "absl/strings/string_view.h"
15 #include "google/protobuf/compiler/rust/context.h"
16 #include "google/protobuf/descriptor.h"
17 #include "google/protobuf/descriptor.pb.h"
18 
19 namespace google {
20 namespace protobuf {
21 namespace compiler {
22 namespace rust {
23 std::string GetCrateName(Context& ctx, const FileDescriptor& dep);
24 
25 std::string GetRsFile(Context& ctx, const FileDescriptor& file);
26 std::string GetThunkCcFile(Context& ctx, const FileDescriptor& file);
27 std::string GetHeaderFile(Context& ctx, const FileDescriptor& file);
28 
29 std::string ThunkName(Context& ctx, const FieldDescriptor& field,
30                       absl::string_view op);
31 std::string ThunkName(Context& ctx, const OneofDescriptor& field,
32                       absl::string_view op);
33 
34 std::string ThunkName(Context& ctx, const Descriptor& msg,
35                       absl::string_view op);
36 std::string RawMapThunk(Context& ctx, const Descriptor& msg,
37                         absl::string_view key_t, absl::string_view op);
38 std::string RawMapThunk(Context& ctx, const EnumDescriptor& desc,
39                         absl::string_view key_t, absl::string_view op);
40 
41 // Returns an absolute path to the Proxied Rust type of the given field.
42 // The absolute path is guaranteed to work in the crate that defines the field.
43 // It may be crate-relative, or directly reference the owning crate of the type.
44 std::string RsTypePath(Context& ctx, const FieldDescriptor& field);
45 
46 // Returns the 'simple spelling' of the Rust View type for the provided field.
47 // For example, `i32` for int32 fields and `SomeMsgView<'$lifetime$>` for
48 // message fields, or `SomeMsgView` if an empty lifetime is provided).
49 //
50 // The returned type will always be functionally substitutable for the
51 // corresponding View<'$lifetime$, $sometype$> of the field's Rust type.
52 std::string RsViewType(Context& ctx, const FieldDescriptor& field,
53                        absl::string_view lifetime);
54 
55 std::string EnumRsName(const EnumDescriptor& desc);
56 std::string EnumValueRsName(const EnumValueDescriptor& value);
57 
58 std::string OneofViewEnumRsName(const OneofDescriptor& oneof);
59 std::string OneofCaseEnumRsName(const OneofDescriptor& oneof);
60 std::string OneofCaseRsName(const FieldDescriptor& oneof_field);
61 
62 std::string FieldInfoComment(Context& ctx, const FieldDescriptor& field);
63 
64 // Return how to name a field with 'collision avoidance'. This adds a suffix
65 // of the field number to the field name if it appears that it will collide with
66 // another field's non-getter accessor.
67 //
68 // For example, for the message:
69 // message M { bool set_x = 1; int32 x = 2; string x_mut = 8; }
70 // All accessors for the field `set_x` will be constructed as though the field
71 // was instead named `set_x_1`, and all accessors for `x_mut` will be as though
72 // the field was instead named `x_mut_8`.
73 //
74 // This is a best-effort heuristic to avoid realistic accidental
75 // collisions. It is still possible to create a message definition that will
76 // have a collision, and it may rename a field even if there's no collision (as
77 // in the case of x_mut in the example).
78 //
79 // Note the returned name may still be a rust keyword: RsSafeName() should
80 // additionally be used if there is no prefix/suffix being appended to the name.
81 std::string FieldNameWithCollisionAvoidance(const FieldDescriptor& field);
82 
83 // Returns how to 'spell' the provided name in Rust, which is the provided name
84 // verbatim unless it is a Rust keyword that isn't a legal symbol name.
85 std::string RsSafeName(absl::string_view name);
86 
87 // Constructs a string of the Rust modules which will contain the message.
88 //
89 // Example: Given a message 'NestedMessage' which is defined in package 'x.y'
90 // which is inside 'ParentMessage', the message will be placed in the
91 // x::y::ParentMessage_ Rust module, so this function will return the string
92 // "x::y::ParentMessage_::".
93 //
94 // If the message has no package and no containing messages then this returns
95 // empty string.
96 std::string RustModuleForContainingType(Context& ctx,
97                                         const Descriptor* containing_type);
98 std::string RustModule(Context& ctx, const Descriptor& msg);
99 std::string RustModule(Context& ctx, const EnumDescriptor& enum_);
100 std::string RustModule(Context& ctx, const OneofDescriptor& oneof);
101 std::string RustInternalModuleName(Context& ctx, const FileDescriptor& file);
102 
103 std::string GetCrateRelativeQualifiedPath(Context& ctx, const Descriptor& msg);
104 std::string GetCrateRelativeQualifiedPath(Context& ctx,
105                                           const EnumDescriptor& enum_);
106 std::string GetCrateRelativeQualifiedPath(Context& ctx,
107                                           const OneofDescriptor& oneof);
108 
109 template <typename Desc>
110 std::string GetUnderscoreDelimitedFullName(Context& ctx, const Desc& desc);
111 
112 std::string UnderscoreDelimitFullName(Context& ctx,
113                                       absl::string_view full_name);
114 
115 // TODO: Unify these with other case-conversion functions.
116 
117 // Converts an UpperCamel or lowerCamel string to a snake_case string.
118 std::string CamelToSnakeCase(absl::string_view input);
119 
120 // Converts a snake_case string to an UpperCamelCase string.
121 std::string SnakeToUpperCamelCase(absl::string_view input);
122 
123 // Converts a SCREAMING_SNAKE_CASE string to an UpperCamelCase string.
124 std::string ScreamingSnakeToUpperCamelCase(absl::string_view input);
125 
126 // Given a fixed prefix, this will repeatedly strip provided
127 // string_views if they start with the prefix, the prefix in UpperCamel, or
128 // the prefix in snake_case.
129 class MultiCasePrefixStripper final {
130  public:
131   explicit MultiCasePrefixStripper(absl::string_view prefix);
132 
133   // Strip a prefix from the name in UpperCamel or snake_case, if present.
134   // If there is an underscore after the prefix, that will also be stripped.
135   // The stripping is case-insensitive.
136   absl::string_view StripPrefix(absl::string_view name) const;
137 
138  private:
139   std::array<std::string, 3> prefixes_;
140 };
141 
142 // More efficient overload if a stripper is already constructed.
143 std::string EnumValueRsName(const MultiCasePrefixStripper& stripper,
144                             absl::string_view value_name);
145 
146 // Describes the names and conversions for a supported map key type.
147 struct MapKeyType {
148   // Identifier used in thunk name.
149   absl::string_view thunk_ident;
150 
151   // Rust key typename (K in Map<K, V>, so e.g. `[u8]` for bytes).
152   // This field may have an unexpanded `$pb$` variable.
153   absl::string_view rs_key_t;
154 
155   // Rust key typename used by thunks for FFI (e.g. `PtrAndLen` for bytes).
156   // This field may have an unexpanded `$pbi$` variable.
157   absl::string_view rs_ffi_key_t;
158 
159   // Rust expression converting `key: rs_key_t` into an `rs_ffi_key_t`.
160   absl::string_view rs_to_ffi_key_expr;
161 
162   // Rust expression converting `ffi_key: rs_ffi_key_t` into an `rs_key_t`.
163   // This field may have an unexpanded `$pb$` variable.
164   absl::string_view rs_from_ffi_key_expr;
165 
166   // C++ key typename (K in Map<K, V>, so e.g. `std::string` for bytes).
167   absl::string_view cc_key_t;
168 
169   // C++ key typename used by thunks for FFI (e.g. `PtrAndLen` for bytes).
170   absl::string_view cc_ffi_key_t;
171 
172   // C++ expression converting `cc_ffi_key_t key` into a `cc_key_t`.
173   absl::string_view cc_from_ffi_key_expr;
174 
175   // C++ expression converting `cc_key_t cpp_key` into a `cc_ffi_key_t`.
176   absl::string_view cc_to_ffi_key_expr;
177 };
178 
179 extern const MapKeyType kMapKeyTypes[6];
180 
181 }  // namespace rust
182 }  // namespace compiler
183 }  // namespace protobuf
184 }  // namespace google
185 
186 #endif  // GOOGLE_PROTOBUF_COMPILER_RUST_NAMING_H__
187