Return the correct view type for messages

$Msg$View is incorrect, we need to actually invoke the getter_thunks. We'll use void* to get us off to the races.

Sprinkled in TODOs as appropriate; and we'll tackle imports in another CL. For now, its important to return the actual raw message, and that's what this CL does for our base uses.

PiperOrigin-RevId: 564785201
pull/13814/head
Hong Shin 1 year ago committed by Copybara-Service
parent 9a0a3cf0cd
commit d72e790084
  1. 3
      rust/test/shared/accessors_test.rs
  2. 37
      src/google/protobuf/compiler/rust/accessors/singular_message.cc
  3. 5
      src/google/protobuf/compiler/rust/generator.cc
  4. 7
      src/google/protobuf/compiler/rust/message.cc
  5. 15
      src/google/protobuf/compiler/rust/naming.cc

@ -364,10 +364,11 @@ fn test_nonempty_default_string_accessors() {
#[test]
fn test_singular_msg_field() {
use crate::TestAllTypes_::NestedMessageView;
let msg = TestAllTypes::new();
// TODO("b/285309454"): fetch the inner integer `bb`
// call should look like msg.optional_nested_message().bb()
let _msg: unittest_proto::proto2_unittest::TestAllTypesView = msg.optional_nested_message();
let _msg: NestedMessageView = msg.optional_nested_message();
}
#[test]

@ -5,9 +5,13 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/rust/accessors/accessor_generator.h"
#include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/compiler/rust/naming.h"
#include "google/protobuf/descriptor.h"
namespace google {
@ -16,29 +20,46 @@ namespace compiler {
namespace rust {
void SingularMessage::InMsgImpl(Context<FieldDescriptor> field) const {
Context<Descriptor> d = field.WithDesc(field.desc().message_type());
auto prefix = "crate::" + GetCrateRelativeQualifiedPath(d);
// here we defer unit tests with messages that have import inside their
// pkg name e.g. unittest_import.proto
if (absl::StrContains(prefix, "import")) {
// TODO(b/285309454): Handle imports correctly, default to $Msg$View for now
prefix = field.desc().containing_type()->name();
}
field.Emit(
{
{"prefix", prefix},
{"field", field.desc().name()},
{"getter_thunk", Thunk(field, "get")},
},
R"rs(
// inMsgImpl
pub fn r#$field$(&self) -> $Msg$View {
$Msg$View { msg: self.inner.msg, _phantom: std::marker::PhantomData }
pub fn r#$field$(&self) -> $prefix$View {
$prefix$View::new($pbi$::Private, unsafe { $getter_thunk$(self.inner.msg) } )
}
)rs");
}
void SingularMessage::InExternC(Context<FieldDescriptor> field) const {
field.Emit({},
R"rs(
// inExternC
field.Emit(
{
{"getter_thunk", Thunk(field, "get")},
},
R"rs(
fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $pbi$::RawMessage;
)rs");
}
void SingularMessage::InThunkCc(Context<FieldDescriptor> field) const {
field.Emit({},
field.Emit({{"QualifiedMsg",
cpp::QualifiedClassName(field.desc().containing_type())},
{"getter_thunk", Thunk(field, "get")},
{"field", cpp::FieldName(&field.desc())}},
R"cc(
// inThunkCC
const void* $getter_thunk$($QualifiedMsg$* msg) {
return static_cast<const void*>(&msg->$field$());
}
)cc");
}

@ -96,6 +96,8 @@ void EmitPubUseOfOwnMessages(Context<FileDescriptor>& primary_file,
primary_file.Emit({{"mod", mod}, {"Msg", name}},
R"rs(
pub use crate::$mod$::$Msg$;
// TODO(b/285309454) Address use for imported crates
pub use crate::$mod$::$Msg$View;
)rs");
}
}
@ -110,10 +112,11 @@ void EmitPubUseForImportedMessages(Context<FileDescriptor>& primary_file,
std::string crate_name = GetCrateName(dep);
for (int i = 0; i < dep.desc().message_type_count(); ++i) {
auto msg = primary_file.WithDesc(dep.desc().message_type(i));
auto path = GetCrateRelativeQualifiedPath(msg);
auto path = GetCrateRelativeQualifiedPath(msg); // TODO: b/300080946
primary_file.Emit({{"crate", crate_name}, {"pkg::Msg", path}},
R"rs(
pub use $crate$::$pkg::Msg$;
pub use $crate$::$pkg::Msg$View;
)rs");
}
}

@ -274,6 +274,13 @@ void GenerateRs(Context<Descriptor> msg) {
_phantom: $Phantom$<&'a ()>,
}
impl<'a> $Msg$View<'a> {
#[doc(hidden)]
pub fn new(_private: $pbi$::Private, msg: $pbi$::RawMessage) -> Self {
Self { msg, _phantom: std::marker::PhantomData }
}
}
// SAFETY:
// - `$Msg$View` does not perform any mutation.
// - While a `$Msg$View` exists, a `$Msg$Mut` can't exist to mutate

@ -10,9 +10,11 @@
#include <string>
#include "absl/log/absl_log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.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"
@ -148,10 +150,19 @@ 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 msg.desc().name();
return name;
}
return absl::StrCat(RustModule(msg), "::", msg.desc().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);
}
std::string FieldInfoComment(Context<FieldDescriptor> field) {

Loading…
Cancel
Save