Clean up of rust messagegenerator and accessor generators.

It ended up being odd to construct the AccessorGenerators ahead of time given some specific Context<>: since each of the three methods on AccessorGenerators demands a different Context than the initial one so they shouldn't hold that Context anyway. It ended up just being a spooky parallel array to the Fields with an unenforced invariant that all methods would be called with a new Context<> but the same underlying FieldDescriptor later.

PiperOrigin-RevId: 558770643
pull/13617/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent da38af7191
commit 34585e9d2f
  1. 6
      src/google/protobuf/compiler/rust/BUILD.bazel
  2. 123
      src/google/protobuf/compiler/rust/accessors/accessor_generator.h
  3. 44
      src/google/protobuf/compiler/rust/accessors/accessors.cc
  4. 57
      src/google/protobuf/compiler/rust/accessors/accessors.h
  5. 20
      src/google/protobuf/compiler/rust/accessors/singular_bytes.cc
  6. 19
      src/google/protobuf/compiler/rust/accessors/singular_message.cc
  7. 20
      src/google/protobuf/compiler/rust/accessors/singular_scalar.cc
  8. 51
      src/google/protobuf/compiler/rust/accessors/unsupported_field.cc
  9. 5
      src/google/protobuf/compiler/rust/generator.cc
  10. 42
      src/google/protobuf/compiler/rust/message.cc
  11. 8
      src/google/protobuf/compiler/rust/message.h

@ -53,8 +53,12 @@ cc_library(
"accessors/singular_bytes.cc", "accessors/singular_bytes.cc",
"accessors/singular_message.cc", "accessors/singular_message.cc",
"accessors/singular_scalar.cc", "accessors/singular_scalar.cc",
"accessors/unsupported_field.cc",
],
hdrs = [
"accessors/accessors.h",
"accessors/accessor_generator.h",
], ],
hdrs = ["accessors/accessors.h"],
copts = COPTS, copts = COPTS,
include_prefix = "google/protobuf/compiler/rust", include_prefix = "google/protobuf/compiler/rust",
deps = [ deps = [

@ -0,0 +1,123 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. 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 LLC. 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.
#ifndef GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSOR_GENERATOR_H__
#define GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSOR_GENERATOR_H__
#include <memory>
#include "absl/log/absl_check.h"
#include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/descriptor.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace rust {
class AccessorGenerator {
public:
AccessorGenerator() = default;
virtual ~AccessorGenerator() = default;
AccessorGenerator(const AccessorGenerator &) = delete;
AccessorGenerator(AccessorGenerator &&) = delete;
AccessorGenerator &operator=(const AccessorGenerator &) = delete;
AccessorGenerator &operator=(AccessorGenerator &&) = delete;
// Constructs a generator for the given field.
//
// Returns `nullptr` if there is no known generator for this field.
static std::unique_ptr<AccessorGenerator> For(Context<FieldDescriptor> field);
void GenerateMsgImpl(Context<FieldDescriptor> field) const {
InMsgImpl(field);
}
void GenerateExternC(Context<FieldDescriptor> field) const {
InExternC(field);
}
void GenerateThunkCc(Context<FieldDescriptor> field) const {
ABSL_CHECK(field.is_cpp());
InThunkCc(field);
}
private:
// Note: the virtual functions are duplicated as non-virtual public functions,
// so that we can customize prologue and epilogue behavior for these
// functions. For example, consider calling `field.printer.WithVars()` as a
// prologue to inject variables automatically.
// Called inside the main inherent `impl Msg {}` block.
virtual void InMsgImpl(Context<FieldDescriptor> field) const {}
// Called inside of a message's `extern "C" {}` block.
virtual void InExternC(Context<FieldDescriptor> field) const {}
// Called inside of an `extern "C" {}` block in the `.thunk.cc` file, if such
// a file is being generated.
virtual void InThunkCc(Context<FieldDescriptor> field) const {}
};
class SingularScalar final : public AccessorGenerator {
public:
~SingularScalar() override = default;
void InMsgImpl(Context<FieldDescriptor> field) const override;
void InExternC(Context<FieldDescriptor> field) const override;
void InThunkCc(Context<FieldDescriptor> field) const override;
};
class SingularBytes final : public AccessorGenerator {
public:
~SingularBytes() override = default;
void InMsgImpl(Context<FieldDescriptor> field) const override;
void InExternC(Context<FieldDescriptor> field) const override;
void InThunkCc(Context<FieldDescriptor> field) const override;
};
class SingularMessage final : public AccessorGenerator {
public:
~SingularMessage() override = default;
void InMsgImpl(Context<FieldDescriptor> field) const override;
void InExternC(Context<FieldDescriptor> field) const override;
void InThunkCc(Context<FieldDescriptor> field) const override;
};
class UnsupportedField final : public AccessorGenerator {
public:
~UnsupportedField() override = default;
void InMsgImpl(Context<FieldDescriptor> field) const override;
};
} // namespace rust
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSOR_GENERATOR_H__

@ -32,6 +32,7 @@
#include <memory> #include <memory>
#include "google/protobuf/compiler/rust/accessors/accessor_generator.h"
#include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor.pb.h"
@ -40,15 +41,22 @@ namespace google {
namespace protobuf { namespace protobuf {
namespace compiler { namespace compiler {
namespace rust { namespace rust {
std::unique_ptr<AccessorGenerator> AccessorGenerator::For(
Context<FieldDescriptor> field) { namespace {
std::unique_ptr<AccessorGenerator> AccessorGeneratorFor(
const FieldDescriptor& desc) {
// We do not support [ctype=FOO] (used to set the field type in C++ to // We do not support [ctype=FOO] (used to set the field type in C++ to
// cord or string_piece) in V0 API. // cord or string_piece) in V0 API.
if (field.desc().options().has_ctype()) { if (desc.options().has_ctype()) {
return nullptr; return std::make_unique<UnsupportedField>();
}
if (desc.is_repeated()) {
return std::make_unique<UnsupportedField>();
} }
switch (field.desc().type()) { switch (desc.type()) {
case FieldDescriptor::TYPE_INT32: case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_INT64: case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_FIXED32: case FieldDescriptor::TYPE_FIXED32:
@ -62,19 +70,31 @@ std::unique_ptr<AccessorGenerator> AccessorGenerator::For(
case FieldDescriptor::TYPE_FLOAT: case FieldDescriptor::TYPE_FLOAT:
case FieldDescriptor::TYPE_DOUBLE: case FieldDescriptor::TYPE_DOUBLE:
case FieldDescriptor::TYPE_BOOL: case FieldDescriptor::TYPE_BOOL:
if (field.desc().is_repeated()) return nullptr; return std::make_unique<SingularScalar>();
return ForSingularScalar(field);
case FieldDescriptor::TYPE_BYTES: case FieldDescriptor::TYPE_BYTES:
if (field.desc().is_repeated()) return nullptr; return std::make_unique<SingularBytes>();
return ForSingularBytes(field);
case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_MESSAGE:
if (field.desc().is_repeated()) return nullptr; return std::make_unique<SingularMessage>();
return ForSingularMessage(field);
default: default:
return nullptr; return std::make_unique<UnsupportedField>();
}
}
} // namespace
void GenerateAccessorMsgImpl(Context<FieldDescriptor> field) {
AccessorGeneratorFor(field.desc())->GenerateMsgImpl(field);
}
void GenerateAccessorExternC(Context<FieldDescriptor> field) {
AccessorGeneratorFor(field.desc())->GenerateExternC(field);
} }
void GenerateAccessorThunkCc(Context<FieldDescriptor> field) {
AccessorGeneratorFor(field.desc())->GenerateThunkCc(field);
} }
} // namespace rust } // namespace rust
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf

@ -31,9 +31,6 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSORS_H__ #ifndef GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSORS_H__
#define GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSORS_H__ #define GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSORS_H__
#include <memory>
#include "absl/log/absl_check.h"
#include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
@ -42,57 +39,9 @@ namespace protobuf {
namespace compiler { namespace compiler {
namespace rust { namespace rust {
class AccessorGenerator { void GenerateAccessorMsgImpl(Context<FieldDescriptor> field);
public: void GenerateAccessorExternC(Context<FieldDescriptor> field);
AccessorGenerator() = default; void GenerateAccessorThunkCc(Context<FieldDescriptor> field);
virtual ~AccessorGenerator() = default;
AccessorGenerator(const AccessorGenerator &) = delete;
AccessorGenerator(AccessorGenerator &&) = delete;
AccessorGenerator &operator=(const AccessorGenerator &) = delete;
AccessorGenerator &operator=(AccessorGenerator &&) = delete;
// Constructs a generator for the given field.
//
// Returns `nullptr` if there is no known generator for this field.
static std::unique_ptr<AccessorGenerator> For(Context<FieldDescriptor> field);
void GenerateMsgImpl(Context<FieldDescriptor> field) const {
InMsgImpl(field);
}
void GenerateExternC(Context<FieldDescriptor> field) const {
InExternC(field);
}
void GenerateThunkCc(Context<FieldDescriptor> field) const {
ABSL_CHECK(field.is_cpp());
InThunkCc(field);
}
private:
// Note: the virtual functions are duplicated as non-virtual public functions,
// so that we can customize prologue and epilogue behavior for these
// functions. For example, consider calling `field.printer.WithVars()` as a
// prologue to inject variables automatically.
// Called inside the main inherent `impl Msg {}` block.
virtual void InMsgImpl(Context<FieldDescriptor> field) const {}
// Called inside of a message's `extern "C" {}` block.
virtual void InExternC(Context<FieldDescriptor> field) const {}
// Called inside of an `extern "C" {}` block in the `.thunk.cc` file, if such
// a file is being generated.
virtual void InThunkCc(Context<FieldDescriptor> field) const {}
// These static factories are defined in the corresponding implementation
// files for each implementation of AccessorGenerator.
static std::unique_ptr<AccessorGenerator> ForSingularScalar(
Context<FieldDescriptor> field);
static std::unique_ptr<AccessorGenerator> ForSingularBytes(
Context<FieldDescriptor> field);
static std::unique_ptr<AccessorGenerator> ForSingularMessage(
Context<FieldDescriptor> field);
};
} // namespace rust } // namespace rust
} // namespace compiler } // namespace compiler

@ -28,11 +28,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/rust/accessors/accessors.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h"
#include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/compiler/rust/naming.h" #include "google/protobuf/compiler/rust/naming.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
@ -41,12 +39,8 @@ namespace google {
namespace protobuf { namespace protobuf {
namespace compiler { namespace compiler {
namespace rust { namespace rust {
namespace {
class SingularBytes final : public AccessorGenerator {
public:
~SingularBytes() override = default;
void InMsgImpl(Context<FieldDescriptor> field) const override { void SingularBytes::InMsgImpl(Context<FieldDescriptor> field) const {
field.Emit( field.Emit(
{ {
{"field", field.desc().name()}, {"field", field.desc().name()},
@ -88,7 +82,7 @@ class SingularBytes final : public AccessorGenerator {
)rs"); )rs");
} }
void InExternC(Context<FieldDescriptor> field) const override { void SingularBytes::InExternC(Context<FieldDescriptor> field) const {
field.Emit({{"hazzer_thunk", Thunk(field, "has")}, field.Emit({{"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", Thunk(field, "get")}, {"getter_thunk", Thunk(field, "get")},
{"setter_thunk", Thunk(field, "set")}, {"setter_thunk", Thunk(field, "set")},
@ -109,7 +103,7 @@ class SingularBytes final : public AccessorGenerator {
)rs"); )rs");
} }
void InThunkCc(Context<FieldDescriptor> field) const override { void SingularBytes::InThunkCc(Context<FieldDescriptor> field) const {
field.Emit({{"field", field.desc().name()}, field.Emit({{"field", field.desc().name()},
{"QualifiedMsg", {"QualifiedMsg",
cpp::QualifiedClassName(field.desc().containing_type())}, cpp::QualifiedClassName(field.desc().containing_type())},
@ -138,13 +132,7 @@ class SingularBytes final : public AccessorGenerator {
void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); }
)cc"); )cc");
} }
};
} // namespace
std::unique_ptr<AccessorGenerator> AccessorGenerator::ForSingularBytes(
Context<FieldDescriptor> field) {
return std::make_unique<SingularBytes>();
}
} // namespace rust } // namespace rust
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf

@ -29,21 +29,16 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "google/protobuf/compiler/rust/accessors/accessors.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h"
#include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/compiler/rust/naming.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
namespace google { namespace google {
namespace protobuf { namespace protobuf {
namespace compiler { namespace compiler {
namespace rust { namespace rust {
namespace {
class SingularMessage final : public AccessorGenerator {
public:
~SingularMessage() override = default;
void InMsgImpl(Context<FieldDescriptor> field) const override { void SingularMessage::InMsgImpl(Context<FieldDescriptor> field) const {
field.Emit( field.Emit(
{ {
{"field", field.desc().name()}, {"field", field.desc().name()},
@ -56,26 +51,20 @@ class SingularMessage final : public AccessorGenerator {
)rs"); )rs");
} }
void InExternC(Context<FieldDescriptor> field) const override { void SingularMessage::InExternC(Context<FieldDescriptor> field) const {
field.Emit({}, field.Emit({},
R"rs( R"rs(
// inExternC // inExternC
)rs"); )rs");
} }
void InThunkCc(Context<FieldDescriptor> field) const override { void SingularMessage::InThunkCc(Context<FieldDescriptor> field) const {
field.Emit({}, field.Emit({},
R"cc( R"cc(
// inThunkCC // inThunkCC
)cc"); )cc");
} }
};
} // namespace
std::unique_ptr<AccessorGenerator> AccessorGenerator::ForSingularMessage(
Context<FieldDescriptor> field) {
return std::make_unique<SingularMessage>();
}
} // namespace rust } // namespace rust
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf

@ -28,11 +28,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/rust/accessors/accessors.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h"
#include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/compiler/rust/naming.h" #include "google/protobuf/compiler/rust/naming.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
@ -41,12 +39,8 @@ namespace google {
namespace protobuf { namespace protobuf {
namespace compiler { namespace compiler {
namespace rust { namespace rust {
namespace {
class SingularScalar final : public AccessorGenerator {
public:
~SingularScalar() override = default;
void InMsgImpl(Context<FieldDescriptor> field) const override { void SingularScalar::InMsgImpl(Context<FieldDescriptor> field) const {
field.Emit( field.Emit(
{ {
{"field", field.desc().name()}, {"field", field.desc().name()},
@ -90,7 +84,7 @@ class SingularScalar final : public AccessorGenerator {
)rs"); )rs");
} }
void InExternC(Context<FieldDescriptor> field) const override { void SingularScalar::InExternC(Context<FieldDescriptor> field) const {
field.Emit( field.Emit(
{{"Scalar", PrimitiveRsTypeName(field)}, {{"Scalar", PrimitiveRsTypeName(field)},
{"hazzer_thunk", Thunk(field, "has")}, {"hazzer_thunk", Thunk(field, "has")},
@ -112,7 +106,7 @@ class SingularScalar final : public AccessorGenerator {
)rs"); )rs");
} }
void InThunkCc(Context<FieldDescriptor> field) const override { void SingularScalar::InThunkCc(Context<FieldDescriptor> field) const {
field.Emit({{"field", cpp::FieldName(&field.desc())}, field.Emit({{"field", cpp::FieldName(&field.desc())},
{"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_type())}, {"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_type())},
{"QualifiedMsg", {"QualifiedMsg",
@ -140,13 +134,7 @@ class SingularScalar final : public AccessorGenerator {
void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); }
)cc"); )cc");
} }
};
} // namespace
std::unique_ptr<AccessorGenerator> AccessorGenerator::ForSingularScalar(
Context<FieldDescriptor> field) {
return std::make_unique<SingularScalar>();
}
} // namespace rust } // namespace rust
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf

@ -0,0 +1,51 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. 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 LLC. 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.
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/rust/accessors/accessor_generator.h"
#include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/descriptor.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace rust {
void UnsupportedField::InMsgImpl(Context<FieldDescriptor> field) const {
field.Emit(R"rs(
// Unsupported! :(
)rs");
field.printer().PrintRaw("\n");
}
} // namespace rust
} // namespace compiler
} // namespace protobuf
} // namespace google

@ -289,8 +289,7 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc,
for (int i = 0; i < file.desc().message_type_count(); ++i) { for (int i = 0; i < file.desc().message_type_count(); ++i) {
auto msg = file.WithDesc(file.desc().message_type(i)); auto msg = file.WithDesc(file.desc().message_type(i));
MessageGenerator gen(msg); GenerateRs(msg);
gen.GenerateRs(msg);
msg.printer().PrintRaw("\n"); msg.printer().PrintRaw("\n");
if (file.is_cpp()) { if (file.is_cpp()) {
@ -299,7 +298,7 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc,
thunks_msg.Emit({{"Msg", msg.desc().full_name()}}, R"cc( thunks_msg.Emit({{"Msg", msg.desc().full_name()}}, R"cc(
// $Msg$ // $Msg$
)cc"); )cc");
gen.GenerateThunksCc(thunks_msg); GenerateThunksCc(thunks_msg);
thunks_msg.printer().PrintRaw("\n"); thunks_msg.printer().PrintRaw("\n");
} }
} }

@ -205,18 +205,7 @@ void MessageDrop(Context<Descriptor> msg) {
} }
} // namespace } // namespace
MessageGenerator::MessageGenerator(Context<Descriptor> msg) { void GenerateRs(Context<Descriptor> msg) {
accessors_.resize(msg.desc().field_count());
for (int i = 0; i < msg.desc().field_count(); ++i) {
auto field = msg.WithDesc(msg.desc().field(i));
accessors_[i] = AccessorGenerator::For(field);
if (accessors_[i] == nullptr) {
ABSL_LOG(WARNING) << "unsupported field: " << field.desc().full_name();
}
}
}
void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
if (msg.desc().map_key() != nullptr) { if (msg.desc().map_key() != nullptr) {
ABSL_LOG(WARNING) << "unsupported map field: " << msg.desc().full_name(); ABSL_LOG(WARNING) << "unsupported map field: " << msg.desc().full_name();
return; return;
@ -233,31 +222,19 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
{"accessor_fns", {"accessor_fns",
[&] { [&] {
for (int i = 0; i < msg.desc().field_count(); ++i) { for (int i = 0; i < msg.desc().field_count(); ++i) {
auto& gen = accessors_[i];
auto field = msg.WithDesc(*msg.desc().field(i)); auto field = msg.WithDesc(*msg.desc().field(i));
msg.Emit({{"comment", FieldInfoComment(field)}}, R"rs( msg.Emit({{"comment", FieldInfoComment(field)}}, R"rs(
// $comment$ // $comment$
)rs"); )rs");
if (gen == nullptr) { GenerateAccessorMsgImpl(field);
msg.Emit({{"field", field.desc().full_name()}}, R"rs(
// Unsupported! :(
)rs");
msg.printer().PrintRaw("\n");
continue;
}
gen->GenerateMsgImpl(field);
msg.printer().PrintRaw("\n"); msg.printer().PrintRaw("\n");
} }
}}, }},
{"accessor_externs", {"accessor_externs",
[&] { [&] {
for (int i = 0; i < msg.desc().field_count(); ++i) { for (int i = 0; i < msg.desc().field_count(); ++i) {
auto& gen = accessors_[i]; GenerateAccessorExternC(msg.WithDesc(*msg.desc().field(i)));
if (gen == nullptr) continue;
gen->GenerateExternC(msg.WithDesc(*msg.desc().field(i)));
msg.printer().PrintRaw("\n"); msg.printer().PrintRaw("\n");
} }
}}, }},
@ -273,8 +250,7 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
++i) { ++i) {
auto nested_msg = auto nested_msg =
msg.WithDesc(msg.desc().nested_type(i)); msg.WithDesc(msg.desc().nested_type(i));
MessageGenerator gen(nested_msg); GenerateRs(nested_msg);
gen.GenerateRs(nested_msg);
} }
}}}, }}},
R"rs( R"rs(
@ -398,7 +374,7 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
} }
// Generates code for a particular message in `.pb.thunk.cc`. // Generates code for a particular message in `.pb.thunk.cc`.
void MessageGenerator::GenerateThunksCc(Context<Descriptor> msg) { void GenerateThunksCc(Context<Descriptor> msg) {
ABSL_CHECK(msg.is_cpp()); ABSL_CHECK(msg.is_cpp());
if (msg.desc().map_key() != nullptr) { if (msg.desc().map_key() != nullptr) {
ABSL_LOG(WARNING) << "unsupported map field: " << msg.desc().full_name(); ABSL_LOG(WARNING) << "unsupported map field: " << msg.desc().full_name();
@ -419,17 +395,13 @@ void MessageGenerator::GenerateThunksCc(Context<Descriptor> msg) {
for (int i = 0; i < msg.desc().nested_type_count(); ++i) { for (int i = 0; i < msg.desc().nested_type_count(); ++i) {
Context<Descriptor> nested_msg = Context<Descriptor> nested_msg =
msg.WithDesc(msg.desc().nested_type(i)); msg.WithDesc(msg.desc().nested_type(i));
MessageGenerator gen(nested_msg); GenerateThunksCc(nested_msg);
gen.GenerateThunksCc(nested_msg);
} }
}}, }},
{"accessor_thunks", {"accessor_thunks",
[&] { [&] {
for (int i = 0; i < msg.desc().field_count(); ++i) { for (int i = 0; i < msg.desc().field_count(); ++i) {
auto& gen = accessors_[i]; GenerateAccessorThunkCc(msg.WithDesc(*msg.desc().field(i)));
if (gen == nullptr) continue;
gen->GenerateThunkCc(msg.WithDesc(*msg.desc().field(i)));
} }
}}, }},
}, },

@ -43,20 +43,12 @@ namespace protobuf {
namespace compiler { namespace compiler {
namespace rust { namespace rust {
class MessageGenerator final {
public:
explicit MessageGenerator(Context<Descriptor> msg);
// Generates code for a particular message in `.pb.rs`. // Generates code for a particular message in `.pb.rs`.
void GenerateRs(Context<Descriptor> msg); void GenerateRs(Context<Descriptor> msg);
// Generates code for a particular message in `.pb.thunk.cc`. // Generates code for a particular message in `.pb.thunk.cc`.
void GenerateThunksCc(Context<Descriptor> msg); void GenerateThunksCc(Context<Descriptor> msg);
private:
std::vector<std::unique_ptr<AccessorGenerator>> accessors_;
};
} // namespace rust } // namespace rust
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf

Loading…
Cancel
Save