From e7a224cd85d3d8f77246c652e50cf6c1a1ce1a10 Mon Sep 17 00:00:00 2001 From: Alyssa Haroldsen Date: Fri, 12 Jan 2024 14:12:27 -0800 Subject: [PATCH] Support enums as oneof fields PiperOrigin-RevId: 597950541 --- rust/test/shared/accessors_proto3_test.rs | 32 +++++ rust/test/shared/accessors_test.rs | 129 ++++++++++++++++----- src/google/protobuf/compiler/rust/oneof.cc | 14 ++- 3 files changed, 144 insertions(+), 31 deletions(-) diff --git a/rust/test/shared/accessors_proto3_test.rs b/rust/test/shared/accessors_proto3_test.rs index aee258fa16..05dff19ca5 100644 --- a/rust/test/shared/accessors_proto3_test.rs +++ b/rust/test/shared/accessors_proto3_test.rs @@ -284,6 +284,22 @@ fn test_oneof_accessors() { assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); } +#[test] +fn test_oneof_enum_accessors() { + use unittest_proto3::proto3_unittest::{ + TestOneof2, + TestOneof2_::{Foo, NestedEnum}, + }; + + let mut msg = TestOneof2::new(); + assert_that!(msg.foo_enum_opt(), eq(Optional::Unset(NestedEnum::Unknown))); + assert_that!(msg.foo(), matches_pattern!(Foo::not_set(_))); + + msg.foo_enum_mut().set(NestedEnum::Bar); + assert_that!(msg.foo_enum_opt(), eq(Optional::Set(NestedEnum::Bar))); + assert_that!(msg.foo(), matches_pattern!(Foo::FooEnum(eq(NestedEnum::Bar)))); +} + #[test] fn test_oneof_mut_accessors() { use TestAllTypes_::OneofFieldMut::*; @@ -317,3 +333,19 @@ fn test_oneof_mut_accessors() { msg.oneof_bytes_mut().set(b"123"); assert_that!(msg.oneof_field_mut(), matches_pattern!(OneofBytes(_))); } + +#[test] +fn test_oneof_mut_enum_accessors() { + use unittest_proto3::proto3_unittest::{ + TestOneof2, + TestOneof2_::{FooMut, NestedEnum}, + }; + + let mut msg = TestOneof2::new(); + assert_that!(msg.foo_enum_opt(), eq(Optional::Unset(NestedEnum::Unknown))); + assert_that!(msg.foo_mut(), matches_pattern!(FooMut::not_set(_))); + + msg.foo_enum_mut().set(NestedEnum::Bar); + assert_that!(msg.foo_enum_opt(), eq(Optional::Set(NestedEnum::Bar))); + assert_that!(msg.foo_mut(), matches_pattern!(FooMut::FooEnum(_))); +} diff --git a/rust/test/shared/accessors_test.rs b/rust/test/shared/accessors_test.rs index edf02159db..f7ee0c0fb1 100644 --- a/rust/test/shared/accessors_test.rs +++ b/rust/test/shared/accessors_test.rs @@ -820,37 +820,42 @@ fn test_default_import_enum_accessors() { #[test] fn test_oneof_accessors() { - use TestAllTypes_::OneofField::*; + use unittest_proto::proto2_unittest::TestOneof2_::{Foo::*, NestedEnum}; - let mut msg = TestAllTypes::new(); - assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); + let mut msg = unittest_proto::proto2_unittest::TestOneof2::new(); + assert_that!(msg.foo(), matches_pattern!(not_set(_))); + + msg.foo_int_mut().set(7); + assert_that!(msg.foo_int_opt(), eq(Optional::Set(7))); + assert_that!(msg.foo(), matches_pattern!(FooInt(eq(7)))); + + msg.foo_int_mut().clear(); + assert_that!(msg.foo_int_opt(), eq(Optional::Unset(0))); + assert_that!(msg.foo(), matches_pattern!(not_set(_))); - msg.oneof_uint32_mut().set(7); - assert_that!(msg.oneof_uint32_opt(), eq(Optional::Set(7))); - assert_that!(msg.oneof_field(), matches_pattern!(OneofUint32(eq(7)))); + msg.foo_int_mut().set(7); + msg.foo_bytes_mut().set(b"123"); + assert_that!(msg.foo_int_opt(), eq(Optional::Unset(0))); - msg.oneof_uint32_mut().clear(); - assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0))); - assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); + assert_that!(msg.foo(), matches_pattern!(FooBytes(eq(b"123")))); - msg.oneof_uint32_mut().set(7); - msg.oneof_bytes_mut().set(b"123"); - assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0))); + msg.foo_enum_mut().set(NestedEnum::Foo); + assert_that!(msg.foo(), matches_pattern!(FooEnum(eq(NestedEnum::Foo)))); - assert_that!(msg.oneof_field(), matches_pattern!(OneofBytes(eq(b"123")))); + // TODO: Add oneof message tests } #[test] fn test_oneof_mut_accessors() { - use TestAllTypes_::OneofFieldMut::*; + use unittest_proto::proto2_unittest::TestOneof2_::{Foo, FooMut::*, NestedEnum}; - let mut msg = TestAllTypes::new(); - assert_that!(msg.oneof_field_mut(), matches_pattern!(not_set(_))); + let mut msg = unittest_proto::proto2_unittest::TestOneof2::new(); + assert_that!(msg.foo_mut(), matches_pattern!(not_set(_))); - msg.oneof_uint32_mut().set(7); + msg.foo_int_mut().set(7); - match msg.oneof_field_mut() { - OneofUint32(mut v) => { + match msg.foo_mut() { + FooInt(mut v) => { assert_that!(v.get(), eq(7)); v.set(8); assert_that!(v.get(), eq(8)); @@ -860,18 +865,84 @@ fn test_oneof_mut_accessors() { // Confirm that the mut write above applies to both the field accessor and the // oneof view accessor. - assert_that!(msg.oneof_uint32_opt(), eq(Optional::Set(8))); - assert_that!( - msg.oneof_field(), - matches_pattern!(TestAllTypes_::OneofField::OneofUint32(eq(8))) - ); + assert_that!(msg.foo_int_opt(), eq(Optional::Set(8))); + assert_that!(msg.foo(), matches_pattern!(Foo::FooInt(_))); + + msg.foo_int_mut().clear(); + assert_that!(msg.foo_mut(), matches_pattern!(not_set(_))); + + msg.foo_int_mut().set(7); + msg.foo_bytes_mut().set(b"123"); + assert_that!(msg.foo_mut(), matches_pattern!(FooBytes(_))); + + msg.foo_enum_mut().set(NestedEnum::Baz); + assert_that!(msg.foo_mut(), matches_pattern!(FooEnum(_))); + + // TODO: Add oneof message tests +} + +#[test] +fn test_oneof_default_accessors() { + use unittest_proto::proto2_unittest::TestOneof2_::{Bar::*, NestedEnum}; + + let mut msg = unittest_proto::proto2_unittest::TestOneof2::new(); + assert_that!(msg.bar(), matches_pattern!(not_set(_))); + + msg.bar_int_mut().set(7); + assert_that!(msg.bar_int_opt(), eq(Optional::Set(7))); + assert_that!(msg.bar(), matches_pattern!(BarInt(eq(7)))); + + msg.bar_int_mut().clear(); + assert_that!(msg.bar_int_opt(), eq(Optional::Unset(5))); + assert_that!(msg.bar(), matches_pattern!(not_set(_))); + + msg.bar_int_mut().set(7); + msg.bar_bytes_mut().set(b"123"); + assert_that!(msg.bar_int_opt(), eq(Optional::Unset(5))); + assert_that!(msg.bar_enum_opt(), eq(Optional::Unset(NestedEnum::Bar))); + assert_that!(msg.bar(), matches_pattern!(BarBytes(eq(b"123")))); + + msg.bar_enum_mut().set(NestedEnum::Baz); + assert_that!(msg.bar(), matches_pattern!(BarEnum(eq(NestedEnum::Baz)))); + assert_that!(msg.bar_int_opt(), eq(Optional::Unset(5))); + + // TODO: Add oneof message tests +} + +#[test] +fn test_oneof_default_mut_accessors() { + use unittest_proto::proto2_unittest::TestOneof2_::{Bar, BarMut::*, NestedEnum}; + + let mut msg = unittest_proto::proto2_unittest::TestOneof2::new(); + assert_that!(msg.bar_mut(), matches_pattern!(not_set(_))); + + msg.bar_int_mut().set(7); + + match msg.bar_mut() { + BarInt(mut v) => { + assert_that!(v.get(), eq(7)); + v.set(8); + assert_that!(v.get(), eq(8)); + } + f => panic!("unexpected field_mut type! {:?}", f), + } + + // Confirm that the mut write above applies to both the field accessor and the + // oneof view accessor. + assert_that!(msg.bar_int_opt(), eq(Optional::Set(8))); + assert_that!(msg.bar(), matches_pattern!(Bar::BarInt(_))); + + msg.bar_int_mut().clear(); + assert_that!(msg.bar_mut(), matches_pattern!(not_set(_))); + + msg.bar_int_mut().set(7); + msg.bar_bytes_mut().set(b"123"); + assert_that!(msg.bar_mut(), matches_pattern!(BarBytes(_))); - msg.oneof_uint32_mut().clear(); - assert_that!(msg.oneof_field_mut(), matches_pattern!(not_set(_))); + msg.bar_enum_mut().set(NestedEnum::Baz); + assert_that!(msg.bar_mut(), matches_pattern!(BarEnum(_))); - msg.oneof_uint32_mut().set(7); - msg.oneof_bytes_mut().set(b"123"); - assert_that!(msg.oneof_field_mut(), matches_pattern!(OneofBytes(_))); + // TODO: Add oneof message tests } #[test] diff --git a/src/google/protobuf/compiler/rust/oneof.cc b/src/google/protobuf/compiler/rust/oneof.cc index 0c041a9e53..afc055038e 100644 --- a/src/google/protobuf/compiler/rust/oneof.cc +++ b/src/google/protobuf/compiler/rust/oneof.cc @@ -104,7 +104,12 @@ std::string RsTypeNameView(Context& ctx, const FieldDescriptor& field) { return ""; } return absl::StrCat("::__pb::View<'msg, ", RsTypePath(ctx, field), ">"); - case FieldDescriptor::TYPE_ENUM: // TODO: b/300257770 - Support enums. + case FieldDescriptor::TYPE_ENUM: + // TODO: support enums which are defined in other crates. + if (!IsInCurrentlyGeneratingCrate(ctx, *field.enum_type())) { + return ""; + } + return absl::StrCat("::__pb::View<'msg, ", RsTypePath(ctx, field), ">"); case FieldDescriptor::TYPE_GROUP: // Not supported yet. return ""; } @@ -144,7 +149,12 @@ std::string RsTypeNameMut(Context& ctx, const FieldDescriptor& field) { return ""; } return absl::StrCat("::__pb::Mut<'msg, ", RsTypePath(ctx, field), ">"); - case FieldDescriptor::TYPE_ENUM: // TODO: b/300257770 - Support enums. + case FieldDescriptor::TYPE_ENUM: + // TODO: support enums which are defined in other crates. + if (!IsInCurrentlyGeneratingCrate(ctx, *field.enum_type())) { + return ""; + } + return absl::StrCat("::__pb::Mut<'msg, ", RsTypePath(ctx, field), ">"); case FieldDescriptor::TYPE_GROUP: // Not supported yet. return ""; }