From 34585e9d2f3cb74aa700b0b9ef3dc78b4168e740 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot <protobuf-github-bot@google.com> Date: Mon, 21 Aug 2023 06:30:02 -0700 Subject: [PATCH] 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 --- src/google/protobuf/compiler/rust/BUILD.bazel | 6 +- .../rust/accessors/accessor_generator.h | 123 +++++++++++++++ .../compiler/rust/accessors/accessors.cc | 44 ++++-- .../compiler/rust/accessors/accessors.h | 57 +------ .../compiler/rust/accessors/singular_bytes.cc | 130 +++++++--------- .../rust/accessors/singular_message.cc | 47 +++--- .../rust/accessors/singular_scalar.cc | 144 ++++++++---------- .../rust/accessors/unsupported_field.cc | 51 +++++++ .../protobuf/compiler/rust/generator.cc | 5 +- src/google/protobuf/compiler/rust/message.cc | 42 +---- src/google/protobuf/compiler/rust/message.h | 16 +- 11 files changed, 370 insertions(+), 295 deletions(-) create mode 100644 src/google/protobuf/compiler/rust/accessors/accessor_generator.h create mode 100644 src/google/protobuf/compiler/rust/accessors/unsupported_field.cc diff --git a/src/google/protobuf/compiler/rust/BUILD.bazel b/src/google/protobuf/compiler/rust/BUILD.bazel index 6936acb8c0..26008b43db 100644 --- a/src/google/protobuf/compiler/rust/BUILD.bazel +++ b/src/google/protobuf/compiler/rust/BUILD.bazel @@ -53,8 +53,12 @@ cc_library( "accessors/singular_bytes.cc", "accessors/singular_message.cc", "accessors/singular_scalar.cc", + "accessors/unsupported_field.cc", + ], + hdrs = [ + "accessors/accessors.h", + "accessors/accessor_generator.h", ], - hdrs = ["accessors/accessors.h"], copts = COPTS, include_prefix = "google/protobuf/compiler/rust", deps = [ diff --git a/src/google/protobuf/compiler/rust/accessors/accessor_generator.h b/src/google/protobuf/compiler/rust/accessors/accessor_generator.h new file mode 100644 index 0000000000..87e8ed886a --- /dev/null +++ b/src/google/protobuf/compiler/rust/accessors/accessor_generator.h @@ -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__ diff --git a/src/google/protobuf/compiler/rust/accessors/accessors.cc b/src/google/protobuf/compiler/rust/accessors/accessors.cc index d0b5ffaa39..1ca22f1dd6 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessors.cc +++ b/src/google/protobuf/compiler/rust/accessors/accessors.cc @@ -32,6 +32,7 @@ #include <memory> +#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" @@ -40,15 +41,22 @@ namespace google { namespace protobuf { namespace compiler { 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 // cord or string_piece) in V0 API. - if (field.desc().options().has_ctype()) { - return nullptr; + if (desc.options().has_ctype()) { + 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_INT64: case FieldDescriptor::TYPE_FIXED32: @@ -62,19 +70,31 @@ std::unique_ptr<AccessorGenerator> AccessorGenerator::For( case FieldDescriptor::TYPE_FLOAT: case FieldDescriptor::TYPE_DOUBLE: case FieldDescriptor::TYPE_BOOL: - if (field.desc().is_repeated()) return nullptr; - return ForSingularScalar(field); + return std::make_unique<SingularScalar>(); case FieldDescriptor::TYPE_BYTES: - if (field.desc().is_repeated()) return nullptr; - return ForSingularBytes(field); + return std::make_unique<SingularBytes>(); case FieldDescriptor::TYPE_MESSAGE: - if (field.desc().is_repeated()) return nullptr; - return ForSingularMessage(field); + return std::make_unique<SingularMessage>(); 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 compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/rust/accessors/accessors.h b/src/google/protobuf/compiler/rust/accessors/accessors.h index 1b4eb7b13f..0fbb09617d 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessors.h +++ b/src/google/protobuf/compiler/rust/accessors/accessors.h @@ -31,9 +31,6 @@ #ifndef 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/descriptor.h" @@ -42,57 +39,9 @@ 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 {} - - // 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); -}; +void GenerateAccessorMsgImpl(Context<FieldDescriptor> field); +void GenerateAccessorExternC(Context<FieldDescriptor> field); +void GenerateAccessorThunkCc(Context<FieldDescriptor> field); } // namespace rust } // namespace compiler diff --git a/src/google/protobuf/compiler/rust/accessors/singular_bytes.cc b/src/google/protobuf/compiler/rust/accessors/singular_bytes.cc index 3380fc6ff7..3deb5a61e4 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_bytes.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_bytes.cc @@ -28,11 +28,9 @@ // (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 <memory> - #include "absl/strings/string_view.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/naming.h" #include "google/protobuf/descriptor.h" @@ -41,24 +39,20 @@ namespace google { namespace protobuf { namespace compiler { namespace rust { -namespace { -class SingularBytes final : public AccessorGenerator { - public: - ~SingularBytes() override = default; - void InMsgImpl(Context<FieldDescriptor> field) const override { - field.Emit( - { - {"field", field.desc().name()}, - {"hazzer_thunk", Thunk(field, "has")}, - {"getter_thunk", Thunk(field, "get")}, - {"setter_thunk", Thunk(field, "set")}, - {"clearer_thunk", Thunk(field, "clear")}, - {"getter_opt", - [&] { - if (!field.desc().is_optional()) return; - if (!field.desc().has_presence()) return; - field.Emit({}, R"rs( +void SingularBytes::InMsgImpl(Context<FieldDescriptor> field) const { + field.Emit( + { + {"field", field.desc().name()}, + {"hazzer_thunk", Thunk(field, "has")}, + {"getter_thunk", Thunk(field, "get")}, + {"setter_thunk", Thunk(field, "set")}, + {"clearer_thunk", Thunk(field, "clear")}, + {"getter_opt", + [&] { + if (!field.desc().is_optional()) return; + if (!field.desc().has_presence()) return; + field.Emit({}, R"rs( pub fn $field$_opt(&self) -> Option<&[u8]> { if !unsafe { $hazzer_thunk$(self.msg) } { return None; @@ -67,9 +61,9 @@ class SingularBytes final : public AccessorGenerator { Some($getter_thunk$(self.msg).as_ref()) } })rs"); - }}, - }, - R"rs( + }}, + }, + R"rs( pub fn r#$field$(&self) -> &[u8] { unsafe { $getter_thunk$(self.msg).as_ref() } } @@ -86,65 +80,59 @@ class SingularBytes final : public AccessorGenerator { } } )rs"); - } +} - void InExternC(Context<FieldDescriptor> field) const override { - field.Emit({{"hazzer_thunk", Thunk(field, "has")}, - {"getter_thunk", Thunk(field, "get")}, - {"setter_thunk", Thunk(field, "set")}, - {"clearer_thunk", Thunk(field, "clear")}, - {"hazzer", - [&] { - if (field.desc().has_presence()) { - field.Emit(R"rs( +void SingularBytes::InExternC(Context<FieldDescriptor> field) const { + field.Emit({{"hazzer_thunk", Thunk(field, "has")}, + {"getter_thunk", Thunk(field, "get")}, + {"setter_thunk", Thunk(field, "set")}, + {"clearer_thunk", Thunk(field, "clear")}, + {"hazzer", + [&] { + if (field.desc().has_presence()) { + field.Emit(R"rs( fn $hazzer_thunk$(raw_msg: $pbi$::RawMessage) -> bool; )rs"); - } - }}}, - R"rs( + } + }}}, + R"rs( $hazzer$ fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $pbi$::PtrAndLen; fn $setter_thunk$(raw_msg: $pbi$::RawMessage, val: *const u8, len: usize); fn $clearer_thunk$(raw_msg: $pbi$::RawMessage); )rs"); - } +} - void InThunkCc(Context<FieldDescriptor> field) const override { - field.Emit({{"field", field.desc().name()}, - {"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")}, - {"hazzer", - [&] { - if (field.desc().has_presence()) { - field.Emit(R"cc( - bool $hazzer_thunk$($QualifiedMsg$* msg) { - return msg->has_$field$(); - })cc"); - } - }}}, - R"cc( - $hazzer$; - ::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 SingularBytes::InThunkCc(Context<FieldDescriptor> field) const { + field.Emit({{"field", field.desc().name()}, + {"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")}, + {"hazzer", + [&] { + if (field.desc().has_presence()) { + field.Emit(R"cc( + bool $hazzer_thunk$($QualifiedMsg$* msg) { + return msg->has_$field$(); + })cc"); } - void $setter_thunk$($QualifiedMsg$* msg, const char* ptr, ::std::size_t size) { - msg->set_$field$(absl::string_view(ptr, size)); - } - void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } - )cc"); - } -}; -} // namespace - -std::unique_ptr<AccessorGenerator> AccessorGenerator::ForSingularBytes( - Context<FieldDescriptor> field) { - return std::make_unique<SingularBytes>(); + }}}, + R"cc( + $hazzer$; + ::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$($QualifiedMsg$* msg, const char* ptr, ::std::size_t size) { + msg->set_$field$(absl::string_view(ptr, size)); + } + void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } + )cc"); } + } // namespace rust } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/rust/accessors/singular_message.cc b/src/google/protobuf/compiler/rust/accessors/singular_message.cc index c10fb086f7..c939714639 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_message.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_message.cc @@ -29,53 +29,42 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #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/naming.h" #include "google/protobuf/descriptor.h" namespace google { namespace protobuf { namespace compiler { namespace rust { -namespace { -class SingularMessage final : public AccessorGenerator { - public: - ~SingularMessage() override = default; - void InMsgImpl(Context<FieldDescriptor> field) const override { - field.Emit( - { - {"field", field.desc().name()}, - }, - R"rs( +void SingularMessage::InMsgImpl(Context<FieldDescriptor> field) const { + field.Emit( + { + {"field", field.desc().name()}, + }, + R"rs( // inMsgImpl pub fn r#$field$(&self) -> $Msg$View { $Msg$View { msg: self.msg, _phantom: std::marker::PhantomData } } )rs"); - } +} - void InExternC(Context<FieldDescriptor> field) const override { - field.Emit({}, - R"rs( +void SingularMessage::InExternC(Context<FieldDescriptor> field) const { + field.Emit({}, + R"rs( // inExternC )rs"); - } - - void InThunkCc(Context<FieldDescriptor> field) const override { - field.Emit({}, - R"cc( - // inThunkCC - )cc"); - } -}; -} // namespace +} -std::unique_ptr<AccessorGenerator> AccessorGenerator::ForSingularMessage( - Context<FieldDescriptor> field) { - return std::make_unique<SingularMessage>(); +void SingularMessage::InThunkCc(Context<FieldDescriptor> field) const { + field.Emit({}, + R"cc( + // inThunkCC + )cc"); } + } // namespace rust } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc index 36ddcdb39c..6be8f44eef 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc @@ -28,11 +28,9 @@ // (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 <memory> - #include "absl/strings/string_view.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/naming.h" #include "google/protobuf/descriptor.h" @@ -41,30 +39,26 @@ namespace google { namespace protobuf { namespace compiler { namespace rust { -namespace { -class SingularScalar final : public AccessorGenerator { - public: - ~SingularScalar() override = default; - void InMsgImpl(Context<FieldDescriptor> field) const override { - field.Emit( - { - {"field", field.desc().name()}, - {"Scalar", PrimitiveRsTypeName(field)}, - {"hazzer_thunk", Thunk(field, "has")}, - {"getter", - [&] { - field.Emit({}, R"rs( +void SingularScalar::InMsgImpl(Context<FieldDescriptor> field) const { + field.Emit( + { + {"field", field.desc().name()}, + {"Scalar", PrimitiveRsTypeName(field)}, + {"hazzer_thunk", Thunk(field, "has")}, + {"getter", + [&] { + field.Emit({}, R"rs( pub fn r#$field$(&self) -> $Scalar$ { unsafe { $getter_thunk$(self.msg) } } )rs"); - }}, - {"getter_opt", - [&] { - if (!field.desc().is_optional()) return; - if (!field.desc().has_presence()) return; - field.Emit({}, R"rs( + }}, + {"getter_opt", + [&] { + if (!field.desc().is_optional()) return; + if (!field.desc().has_presence()) return; + field.Emit({}, R"rs( pub fn r#$field$_opt(&self) -> Option<$Scalar$> { if !unsafe { $hazzer_thunk$(self.msg) } { return None; @@ -72,12 +66,12 @@ class SingularScalar final : public AccessorGenerator { Some(unsafe { $getter_thunk$(self.msg) }) } )rs"); - }}, - {"getter_thunk", Thunk(field, "get")}, - {"setter_thunk", Thunk(field, "set")}, - {"clearer_thunk", Thunk(field, "clear")}, - }, - R"rs( + }}, + {"getter_thunk", Thunk(field, "get")}, + {"setter_thunk", Thunk(field, "set")}, + {"clearer_thunk", Thunk(field, "clear")}, + }, + R"rs( $getter$ $getter_opt$ @@ -88,65 +82,59 @@ class SingularScalar final : public AccessorGenerator { } } )rs"); - } +} - void InExternC(Context<FieldDescriptor> field) const override { - field.Emit( - {{"Scalar", PrimitiveRsTypeName(field)}, - {"hazzer_thunk", Thunk(field, "has")}, - {"getter_thunk", Thunk(field, "get")}, - {"setter_thunk", Thunk(field, "set")}, - {"clearer_thunk", Thunk(field, "clear")}, - {"hazzer", - [&] { - if (field.desc().has_presence()) { - field.Emit( - R"rs(fn $hazzer_thunk$(raw_msg: $pbi$::RawMessage) -> bool;)rs"); - } - }}}, - R"rs( +void SingularScalar::InExternC(Context<FieldDescriptor> field) const { + field.Emit( + {{"Scalar", PrimitiveRsTypeName(field)}, + {"hazzer_thunk", Thunk(field, "has")}, + {"getter_thunk", Thunk(field, "get")}, + {"setter_thunk", Thunk(field, "set")}, + {"clearer_thunk", Thunk(field, "clear")}, + {"hazzer", + [&] { + if (field.desc().has_presence()) { + field.Emit( + R"rs(fn $hazzer_thunk$(raw_msg: $pbi$::RawMessage) -> bool;)rs"); + } + }}}, + R"rs( $hazzer$ fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $Scalar$; fn $setter_thunk$(raw_msg: $pbi$::RawMessage, val: $Scalar$); fn $clearer_thunk$(raw_msg: $pbi$::RawMessage); )rs"); - } +} - void InThunkCc(Context<FieldDescriptor> field) const override { - field.Emit({{"field", cpp::FieldName(&field.desc())}, - {"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_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")}, - {"hazzer", - [&] { - if (field.desc().has_presence()) { - field.Emit(R"cc( - bool $hazzer_thunk$($QualifiedMsg$* msg) { - return msg->has_$field$(); - } - )cc"); - } - }}}, - R"cc( - $hazzer$; - $Scalar$ $getter_thunk$($QualifiedMsg$* msg) { return msg->$field$(); } - void $setter_thunk$($QualifiedMsg$* msg, $Scalar$ val) { - msg->set_$field$(val); +void SingularScalar::InThunkCc(Context<FieldDescriptor> field) const { + field.Emit({{"field", cpp::FieldName(&field.desc())}, + {"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_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")}, + {"hazzer", + [&] { + if (field.desc().has_presence()) { + field.Emit(R"cc( + bool $hazzer_thunk$($QualifiedMsg$* msg) { + return msg->has_$field$(); + } + )cc"); } - void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } - )cc"); - } -}; -} // namespace - -std::unique_ptr<AccessorGenerator> AccessorGenerator::ForSingularScalar( - Context<FieldDescriptor> field) { - return std::make_unique<SingularScalar>(); + }}}, + R"cc( + $hazzer$; + $Scalar$ $getter_thunk$($QualifiedMsg$* msg) { return msg->$field$(); } + void $setter_thunk$($QualifiedMsg$* msg, $Scalar$ val) { + msg->set_$field$(val); + } + void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } + )cc"); } + } // namespace rust } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc b/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc new file mode 100644 index 0000000000..f8ff82151a --- /dev/null +++ b/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc @@ -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 diff --git a/src/google/protobuf/compiler/rust/generator.cc b/src/google/protobuf/compiler/rust/generator.cc index 02a92a6dc7..a3668a485d 100644 --- a/src/google/protobuf/compiler/rust/generator.cc +++ b/src/google/protobuf/compiler/rust/generator.cc @@ -289,8 +289,7 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc, for (int i = 0; i < file.desc().message_type_count(); ++i) { auto msg = file.WithDesc(file.desc().message_type(i)); - MessageGenerator gen(msg); - gen.GenerateRs(msg); + GenerateRs(msg); msg.printer().PrintRaw("\n"); 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( // $Msg$ )cc"); - gen.GenerateThunksCc(thunks_msg); + GenerateThunksCc(thunks_msg); thunks_msg.printer().PrintRaw("\n"); } } diff --git a/src/google/protobuf/compiler/rust/message.cc b/src/google/protobuf/compiler/rust/message.cc index a42c550c09..64027f97ab 100644 --- a/src/google/protobuf/compiler/rust/message.cc +++ b/src/google/protobuf/compiler/rust/message.cc @@ -205,18 +205,7 @@ void MessageDrop(Context<Descriptor> msg) { } } // namespace -MessageGenerator::MessageGenerator(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) { +void GenerateRs(Context<Descriptor> msg) { if (msg.desc().map_key() != nullptr) { ABSL_LOG(WARNING) << "unsupported map field: " << msg.desc().full_name(); return; @@ -233,31 +222,19 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) { {"accessor_fns", [&] { for (int i = 0; i < msg.desc().field_count(); ++i) { - auto& gen = accessors_[i]; auto field = msg.WithDesc(*msg.desc().field(i)); msg.Emit({{"comment", FieldInfoComment(field)}}, R"rs( // $comment$ )rs"); - if (gen == nullptr) { - msg.Emit({{"field", field.desc().full_name()}}, R"rs( - // Unsupported! :( - )rs"); - msg.printer().PrintRaw("\n"); - continue; - } - - gen->GenerateMsgImpl(field); + GenerateAccessorMsgImpl(field); msg.printer().PrintRaw("\n"); } }}, {"accessor_externs", [&] { for (int i = 0; i < msg.desc().field_count(); ++i) { - auto& gen = accessors_[i]; - if (gen == nullptr) continue; - - gen->GenerateExternC(msg.WithDesc(*msg.desc().field(i))); + GenerateAccessorExternC(msg.WithDesc(*msg.desc().field(i))); msg.printer().PrintRaw("\n"); } }}, @@ -273,8 +250,7 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) { ++i) { auto nested_msg = msg.WithDesc(msg.desc().nested_type(i)); - MessageGenerator gen(nested_msg); - gen.GenerateRs(nested_msg); + GenerateRs(nested_msg); } }}}, R"rs( @@ -398,7 +374,7 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) { } // 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()); if (msg.desc().map_key() != nullptr) { 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) { Context<Descriptor> nested_msg = msg.WithDesc(msg.desc().nested_type(i)); - MessageGenerator gen(nested_msg); - gen.GenerateThunksCc(nested_msg); + GenerateThunksCc(nested_msg); } }}, {"accessor_thunks", [&] { for (int i = 0; i < msg.desc().field_count(); ++i) { - auto& gen = accessors_[i]; - if (gen == nullptr) continue; - - gen->GenerateThunkCc(msg.WithDesc(*msg.desc().field(i))); + GenerateAccessorThunkCc(msg.WithDesc(*msg.desc().field(i))); } }}, }, diff --git a/src/google/protobuf/compiler/rust/message.h b/src/google/protobuf/compiler/rust/message.h index 608c69a56b..ad8ab8037e 100644 --- a/src/google/protobuf/compiler/rust/message.h +++ b/src/google/protobuf/compiler/rust/message.h @@ -43,19 +43,11 @@ namespace protobuf { namespace compiler { namespace rust { -class MessageGenerator final { - public: - explicit MessageGenerator(Context<Descriptor> msg); +// Generates code for a particular message in `.pb.rs`. +void GenerateRs(Context<Descriptor> msg); - // Generates code for a particular message in `.pb.rs`. - void GenerateRs(Context<Descriptor> msg); - - // Generates code for a particular message in `.pb.thunk.cc`. - void GenerateThunksCc(Context<Descriptor> msg); - - private: - std::vector<std::unique_ptr<AccessorGenerator>> accessors_; -}; +// Generates code for a particular message in `.pb.thunk.cc`. +void GenerateThunksCc(Context<Descriptor> msg); } // namespace rust } // namespace compiler