Skip to content

Commit

Permalink
Small clean up Rust crate-relative naming logic
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 579243379
  • Loading branch information
protobuf-github-bot authored and copybara-github committed Nov 3, 2023
1 parent 25f28ee commit af75cb3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 18 deletions.
12 changes: 12 additions & 0 deletions rust/test/nested.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ message Outer {
message Inner {
optional int32 num = 1;
optional bool boolean = 2;

message SuperInner {
message DuperInner {
message EvenMoreInner {
message CantBelieveItsSoInner {
optional int32 num = 99;
}
}
}
}
}
optional Inner inner = 1;
optional .nest.Outer.Inner.SuperInner.DuperInner.EvenMoreInner
.CantBelieveItsSoInner deep = 2;
}
10 changes: 10 additions & 0 deletions rust/test/shared/simple_nested_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,13 @@ fn test_simple_nested_proto() {
assert_eq!(outer_msg.inner().num(), 0);
assert!(!outer_msg.inner().boolean());
}

#[test]
fn test_deeply_nested_definition() {
let deep = nested_proto::nest::Outer_::Inner_::SuperInner_::DuperInner_::EvenMoreInner_
::CantBelieveItsSoInner::new();
assert_eq!(deep.num(), 0);

let outer_msg = Outer::new();
assert_eq!(outer_msg.deep().num(), 0);
}
61 changes: 43 additions & 18 deletions src/google/protobuf/compiler/rust/naming.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
#include "google/protobuf/compiler/rust/naming.h"

#include <string>
#include <vector>

#include "absl/log/absl_log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/strings/substitute.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/rust/context.h"
Expand Down Expand Up @@ -166,10 +167,46 @@ std::string PrimitiveRsTypeName(const FieldDescriptor& desc) {
return "";
}

// Constructs a string of the Rust modules which will contain the message.
//
// Example: Given a message 'NestedMessage' which is defined in package 'x.y'
// which is inside 'ParentMessage', the message will be placed in the
// x::y::ParentMessage_ Rust module, so this function will return the string
// "x::y::ParentMessage_::".
//
// If the message has no package and no containing messages then this returns
// empty string.
std::string RustModule(Context<Descriptor> msg) {
absl::string_view package = msg.desc().file()->package();
if (package.empty()) return "";
return absl::StrCat("", absl::StrReplaceAll(package, {{".", "::"}}));
const Descriptor& desc = msg.desc();

std::vector<std::string> modules;

std::vector<std::string> package_modules =
absl::StrSplit(desc.file()->package(), '.', absl::SkipEmpty());

modules.insert(modules.begin(), package_modules.begin(),
package_modules.end());

// Innermost to outermost order.
std::vector<std::string> modules_from_containing_types;
const Descriptor* parent = desc.containing_type();
while (parent != nullptr) {
modules_from_containing_types.push_back(absl::StrCat(parent->name(), "_"));
parent = parent->containing_type();
}

// Add the modules from containing messages (rbegin/rend to get them in outer
// to inner order).
modules.insert(modules.end(), modules_from_containing_types.rbegin(),
modules_from_containing_types.rend());

// If there is any modules at all, push an empty string on the end so that
// we get the trailing ::
if (!modules.empty()) {
modules.push_back("");
}

return absl::StrJoin(modules, "::");
}

std::string RustInternalModuleName(Context<FileDescriptor> file) {
Expand All @@ -179,19 +216,7 @@ std::string RustInternalModuleName(Context<FileDescriptor> file) {
}

std::string GetCrateRelativeQualifiedPath(Context<Descriptor> msg) {
std::string name = msg.desc().full_name();
if (msg.desc().file()->package().empty()) {
return name;
}
// when computing the relative path, we don't want the package name, so we
// strip that out
name =
std::string(absl::StripPrefix(name, msg.desc().file()->package() + "."));
// proto nesting is marked with periods in .proto files -- this gets
// translated to delimiting via _:: in terra rust
absl::StrReplaceAll({{".", "_::"}}, &name);

return absl::StrCat(RustModule(msg), "::", name);
return absl::StrCat(RustModule(msg), msg.desc().name());
}

std::string FieldInfoComment(Context<FieldDescriptor> field) {
Expand Down

0 comments on commit af75cb3

Please sign in to comment.