Implement nested messages for v0 API for cpp kernel

PiperOrigin-RevId: 525372222
pull/12501/head
Marcel Hlopko 2 years ago committed by Copybara-Service
parent 22d0a354a0
commit e5679c01e8
  1. 10
      rust/test/cpp/BUILD
  2. 2
      rust/test/cpp/accessors_test.rs
  3. 39
      rust/test/cpp/nested_messages_test.rs
  4. 12
      src/google/protobuf/compiler/rust/accessors/singular_bytes.cc
  5. 11
      src/google/protobuf/compiler/rust/accessors/singular_scalar.cc
  6. 2
      src/google/protobuf/compiler/rust/generator.cc
  7. 66
      src/google/protobuf/compiler/rust/message.cc
  8. 2
      src/google/protobuf/compiler/rust/message.h

@ -21,3 +21,13 @@ rust_test(
],
deps = ["//rust/test:unittest_cc_rust_proto"],
)
rust_test(
name = "nested_messages_test",
srcs = ["nested_messages_test.rs"],
tags = [
# TODO(b/270274576): Enable testing on arm once we have a Rust Arm toolchain.
"not_build:arm",
],
deps = ["//rust/test:unittest_cc_rust_proto"],
)

@ -28,7 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// Tests covering accessors for singular bool and int64 fields.
/// Tests covering accessors for singular bool, int64, and bytes fields.
use unittest_proto::proto2_unittest::TestAllTypes;
#[test]

@ -0,0 +1,39 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// Tests covering nested messages.
#[test]
fn test_nested_messages_accesible() {
let _parent: unittest_proto::proto2_unittest::TestAllTypes;
let _child: unittest_proto::proto2_unittest::TestAllTypes_::NestedMessage;
unittest_proto::proto2_unittest::TestChildExtensionData_::
NestedTestAllExtensionsData_::NestedDynamicExtensions::new();
}

@ -94,25 +94,25 @@ class SingularBytes final : public AccessorGenerator {
field.Emit(
{
{"field", field.desc().name()},
{"namespace", cpp::Namespace(field.desc().containing_type())},
{"QualifiedMsg",
cpp::QualifiedClassName(field.desc().containing_type())},
{"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", Thunk(field, "get")},
{"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", Thunk(field, "clear")},
},
R"cc(
bool $hazzer_thunk$($namespace$::$Msg$* msg) {
bool $hazzer_thunk$($QualifiedMsg$* msg) {
return msg->has_$field$();
}
::google::protobuf::rust_internal::PtrAndLen $getter_thunk$($namespace$::$Msg$* msg) {
::google::protobuf::rust_internal::PtrAndLen $getter_thunk$($QualifiedMsg$* msg) {
absl::string_view val = msg->$field$();
return google::protobuf::rust_internal::PtrAndLen(val.data(), val.size());
}
void $setter_thunk$($namespace$::$Msg$* msg, const char* ptr,
::std::size_t size) {
void $setter_thunk$($QualifiedMsg$* msg, const char* ptr, ::std::size_t size) {
msg->set_$field$(absl::string_view(ptr, size));
}
void $clearer_thunk$($namespace$::$Msg$* msg) { msg->clear_$field$(); }
void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); }
)cc");
}
};

@ -94,21 +94,22 @@ class SingularScalar final : public AccessorGenerator {
{
{"field", field.desc().name()},
{"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_type())},
{"namespace", cpp::Namespace(field.desc().containing_type())},
{"QualifiedMsg",
cpp::QualifiedClassName(field.desc().containing_type())},
{"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", Thunk(field, "get")},
{"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", Thunk(field, "clear")},
},
R"cc(
bool $hazzer_thunk$($namespace$::$Msg$* msg) {
bool $hazzer_thunk$($QualifiedMsg$* msg) {
return msg->has_$field$();
}
$Scalar$ $getter_thunk$($namespace$::$Msg$* msg) { return msg->$field$(); }
void $setter_thunk$($namespace$::$Msg$* msg, $Scalar$ val) {
$Scalar$ $getter_thunk$($QualifiedMsg$* msg) { return msg->$field$(); }
void $setter_thunk$($QualifiedMsg$* msg, $Scalar$ val) {
msg->set_$field$(val);
}
void $clearer_thunk$($namespace$::$Msg$* msg) { msg->clear_$field$(); }
void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); }
)cc");
}
};

@ -153,7 +153,7 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc,
thunks_msg.Emit({{"Msg", msg.desc().full_name()}}, R"cc(
// $Msg$
)cc");
gen.GenerateThunkCc(thunks_msg);
gen.GenerateThunksCc(thunks_msg);
thunks_msg.printer().PrintRaw("\n");
}
}

@ -32,6 +32,8 @@
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/cpp/names.h"
#include "google/protobuf/compiler/rust/accessors/accessors.h"
#include "google/protobuf/compiler/rust/context.h"
@ -239,6 +241,28 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
msg.printer().PrintRaw("\n");
}
}},
{"nested_msgs",
[&] {
if (msg.desc().nested_type_count() == 0) {
return;
}
msg.Emit({{"Msg", msg.desc().name()},
{"nested_msgs",
[&] {
for (int i = 0; i < msg.desc().nested_type_count();
++i) {
auto nested_msg =
msg.WithDesc(msg.desc().nested_type(i));
MessageGenerator gen(nested_msg);
gen.GenerateRs(nested_msg);
}
}}},
R"rs(
pub mod $Msg$_ {
$nested_msgs$
} // mod $Msg$_
)rs");
}},
},
R"rs(
#[allow(non_camel_case_types)]
@ -274,6 +298,8 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
$accessor_externs$
} // extern "C" for $Msg$
$nested_msgs$
)rs");
if (msg.is_cpp()) {
@ -289,18 +315,27 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
}
// Generates code for a particular message in `.pb.thunk.cc`.
void MessageGenerator::GenerateThunkCc(Context<Descriptor> msg) {
void MessageGenerator::GenerateThunksCc(Context<Descriptor> msg) {
ABSL_CHECK(msg.is_cpp());
msg.Emit(
{
{"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode.
{"Msg", msg.desc().name()},
{"pkg", cpp::Namespace(&msg.desc())},
{"QualifiedMsg", cpp::QualifiedClassName(&msg.desc())},
{"new_thunk", Thunk(msg, "new")},
{"delete_thunk", Thunk(msg, "delete")},
{"serialize_thunk", Thunk(msg, "serialize")},
{"deserialize_thunk", Thunk(msg, "deserialize")},
{"nested_msg_thunks",
[&] {
for (int i = 0; i < msg.desc().nested_type_count(); ++i) {
Context<Descriptor> nested_msg =
msg.WithDesc(msg.desc().nested_type(i));
MessageGenerator gen(nested_msg);
gen.GenerateThunksCc(nested_msg);
}
}},
{"accessor_thunks",
[&] {
for (int i = 0; i < msg.desc().field_count(); ++i) {
@ -312,19 +347,26 @@ void MessageGenerator::GenerateThunkCc(Context<Descriptor> msg) {
}},
},
R"cc(
// $abi$ is a workaround for a syntax highlight bug in VSCode. However,
// that confuses clang-format (it refuses to keep the newline after
// `$abi${`). Disabling clang-format for the block.
// clang-format off
extern $abi$ {
void* $new_thunk$() { return new $pkg$::$Msg$(); }
void $delete_thunk$(void* ptr) { delete static_cast<$pkg$::$Msg$*>(ptr); }
google::protobuf::rust_internal::SerializedData $serialize_thunk$($pkg$::$Msg$ * msg) {
return google::protobuf::rust_internal::SerializeMsg(msg);
}
bool $deserialize_thunk$($pkg$::$Msg$ * msg,
google::protobuf::rust_internal::SerializedData data) {
return msg->ParseFromArray(data.data, data.len);
}
void * $new_thunk$(){return new $QualifiedMsg$(); }
void $delete_thunk$(void* ptr) { delete static_cast<$QualifiedMsg$*>(ptr); }
google::protobuf::rust_internal::SerializedData $serialize_thunk$($QualifiedMsg$* msg) {
return google::protobuf::rust_internal::SerializeMsg(msg);
}
bool $deserialize_thunk$($QualifiedMsg$* msg,
google::protobuf::rust_internal::SerializedData data) {
return msg->ParseFromArray(data.data, data.len);
}
$accessor_thunks$
$accessor_thunks$
} // extern $abi$
// clang-format on
$nested_msg_thunks$
)cc");
}

@ -51,7 +51,7 @@ class MessageGenerator final {
void GenerateRs(Context<Descriptor> msg);
// Generates code for a particular message in `.pb.thunk.cc`.
void GenerateThunkCc(Context<Descriptor> msg);
void GenerateThunksCc(Context<Descriptor> msg);
private:
std::vector<std::unique_ptr<AccessorGenerator>> accessors_;

Loading…
Cancel
Save