Add support for `oneof` fields in a `proto_parsing::Message`

This change adds a way for `proto_parsing::Message` implementations to handle `oneof` fields. This can be done as follows:
```c++
class OneofTestMessageTP : public Message {
 public:
  enum MyOneofCase {
    MY_ONEOF_NOT_SET = 0,
    kFieldA = 1,
    kFieldB = 2,
  };

  OneofTestMessageTP() = default;
  OneofTestMessageTP(const OneofTestMessageTP&) = default;
  OneofTestMessageTP& operator=(const OneofTestMessageTP&) = default;

  MyOneofCase my_oneof_case() const { return my_oneof_case_; }

  // Accessors for field_a (uint32)
  bool has_field_a() const { return field_a_.has_value(); }
  uint32_t field_a() const { return field_a_.value(); }
  void set_field_a(uint32_t val) {
    BeforeFieldSet(&field_a_);
    field_a_.set_value(val);
  }
  void clear_field_a() {
    if (my_oneof_case_ == kFieldA) {
      my_oneof_case_ = MY_ONEOF_NOT_SET;
    }
    field_a_.Clear();
  }

  // Accessors for field_b (bytes/string)
  bool has_field_b() const { return field_b_.has_value(); }
  const std::string& field_b() const { return field_b_.value(); }
  void set_field_b(absl::string_view val) {
    BeforeFieldSet(&field_b_);
    field_b_.set_value(val);
  }
  void clear_field_b() {
    if (my_oneof_case_ == kFieldB) {
      my_oneof_case_ = MY_ONEOF_NOT_SET;
    }
    field_b_.Clear();
  }

  void Clear() override {
    ::tink_proto::Message::Clear();
    my_oneof_case_ = MY_ONEOF_NOT_SET;
  }

 protected:
  // Hook called by ParseFromString AND setters to enforce mutual exclusion
  void BeforeFieldSet(const ::tink_proto::Field* field) override {
    if (field == &field_a_ || field == &field_b_) {
      MyOneofCase parsed_case = static_cast<MyOneofCase>(field->FieldNumber());
      if (my_oneof_case_ == parsed_case) {
        return; // Allows submessage merging if the same field is parsed again
      }
      if (my_oneof_case_ == kFieldA) {
        field_a_.Clear();
      } else if (my_oneof_case_ == kFieldB) {
        field_b_.Clear();
      }
      my_oneof_case_ = parsed_case;
    }
  }

 private:
  size_t num_fields() const override { return 2; }
  const ::tink_proto::Field* field(int i) const override {
    return std::array<const ::tink_proto::Field*, 2>{{&field_a_, &field_b_}}[i];
  }

  ::tink_proto::Uint32Field field_a_{1, ::tink_proto::ProtoFieldOptions::kExplicit};
  ::tink_proto::BytesField field_b_{2, ::tink_proto::ProtoFieldOptions::kExplicit};

  MyOneofCase my_oneof_case_ = MY_ONEOF_NOT_SET;
};
```

PiperOrigin-RevId: 947020621
Change-Id: I2f1baeff0043723413366b72d1c992382f525fc0
diff --git a/tink/internal/proto_parser_message.cc b/tink/internal/proto_parser_message.cc
index 9db155c..f3fd16c 100644
--- a/tink/internal/proto_parser_message.cc
+++ b/tink/internal/proto_parser_message.cc
@@ -176,6 +176,7 @@
       }
       continue;
     }
+    BeforeFieldSet(field);
     if (!const_cast<Field*>(field)->ConsumeIntoMember(in)) {
       return false;
     }
diff --git a/tink/internal/proto_parser_message.h b/tink/internal/proto_parser_message.h
index 9504bec..5feaa3b 100644
--- a/tink/internal/proto_parser_message.h
+++ b/tink/internal/proto_parser_message.h
@@ -78,7 +78,7 @@
 
   // Methods taken from the proto2::Message interface.
   // Clears all fields.
-  void Clear();
+  virtual void Clear();
   bool ParseFromString(absl::string_view in);
   size_t ByteSizeLong() const;
 
@@ -123,6 +123,10 @@
   //   * 0 <= i < num_fields().
   //   * The fields are sorted by field number.
   virtual const Field* field(int i) const = 0;
+
+  // Hook called during parsing or setter invocation when a field belongs to a
+  // oneof.
+  virtual void BeforeFieldSet(const Field* field) {}
 };
 
 // Base class for RepeatedMessageField.
diff --git a/tink/internal/proto_parser_message_test.cc b/tink/internal/proto_parser_message_test.cc
index 2862081..868f87e 100644
--- a/tink/internal/proto_parser_message_test.cc
+++ b/tink/internal/proto_parser_message_test.cc
@@ -115,6 +115,107 @@
   MessageField<InnerStruct> inner_member_{1};
 };
 
+class OneofTestMessageTP : public Message {
+ public:
+  enum MyOneof1Case {
+    MY_ONEOF_1_NOT_SET = 0,
+    kFieldA = 1,
+    kFieldB = 2,
+  };
+  enum MyOneof2Case {
+    MY_ONEOF_2_NOT_SET = 0,
+    kFieldC = 3,
+    kFieldD = 4,
+  };
+
+  OneofTestMessageTP() = default;
+  OneofTestMessageTP(const OneofTestMessageTP&) = default;
+  OneofTestMessageTP& operator=(const OneofTestMessageTP&) = default;
+
+  MyOneof1Case my_oneof_1_case() const { return my_oneof_1_case_; }
+  MyOneof2Case my_oneof_2_case() const { return my_oneof_2_case_; }
+
+  // Oneof 1
+  bool has_field_a() const { return field_a_.has_value(); }
+  const InnerStruct& field_a() const { return field_a_.value(); }
+  InnerStruct* mutable_field_a() {
+    BeforeFieldSet(&field_a_);
+    return field_a_.mutable_value();
+  }
+
+  bool has_field_b() const { return field_b_.has_value(); }
+  uint32_t field_b() const { return field_b_.value(); }
+  void set_field_b(uint32_t val) {
+    BeforeFieldSet(&field_b_);
+    field_b_.set_value(val);
+  }
+
+  // Oneof 2
+  bool has_field_c() const { return field_c_.has_value(); }
+  uint32_t field_c() const { return field_c_.value(); }
+  void set_field_c(uint32_t val) {
+    BeforeFieldSet(&field_c_);
+    field_c_.set_value(val);
+  }
+
+  bool has_field_d() const { return field_d_.has_value(); }
+  uint32_t field_d() const { return field_d_.value(); }
+  void set_field_d(uint32_t val) {
+    BeforeFieldSet(&field_d_);
+    field_d_.set_value(val);
+  }
+
+  void Clear() override {
+    Message::Clear();
+    my_oneof_1_case_ = MY_ONEOF_1_NOT_SET;
+    my_oneof_2_case_ = MY_ONEOF_2_NOT_SET;
+  }
+
+ protected:
+  void BeforeFieldSet(const Field* field) override {
+    if (field == &field_a_ || field == &field_b_) {
+      MyOneof1Case parsed_case =
+          static_cast<MyOneof1Case>(field->FieldNumber());
+      if (my_oneof_1_case_ == parsed_case) {
+        return;
+      }
+      if (my_oneof_1_case_ == kFieldA) {
+        field_a_.Clear();
+      } else if (my_oneof_1_case_ == kFieldB) {
+        field_b_.Clear();
+      }
+      my_oneof_1_case_ = parsed_case;
+    } else if (field == &field_c_ || field == &field_d_) {
+      MyOneof2Case parsed_case =
+          static_cast<MyOneof2Case>(field->FieldNumber());
+      if (my_oneof_2_case_ == parsed_case) {
+        return;
+      }
+      if (my_oneof_2_case_ == kFieldC) {
+        field_c_.Clear();
+      } else if (my_oneof_2_case_ == kFieldD) {
+        field_d_.Clear();
+      }
+      my_oneof_2_case_ = parsed_case;
+    }
+  }
+
+ private:
+  size_t num_fields() const override { return 4; }
+  const Field* field(int i) const override {
+    return std::array<const Field*, 4>{
+        {&field_a_, &field_b_, &field_c_, &field_d_}}[i];
+  }
+
+  MessageField<InnerStruct> field_a_{1, ProtoFieldOptions::kExplicit};
+  Uint32Field field_b_{2, ProtoFieldOptions::kExplicit};
+  Uint32Field field_c_{3, ProtoFieldOptions::kExplicit};
+  Uint32Field field_d_{4, ProtoFieldOptions::kExplicit};
+
+  MyOneof1Case my_oneof_1_case_ = MY_ONEOF_1_NOT_SET;
+  MyOneof2Case my_oneof_2_case_ = MY_ONEOF_2_NOT_SET;
+};
+
 TEST(MessageTest, Clear) {
   OuterStruct s;
   s.mutable_inner_member()->set_uint32_member_1(123);
@@ -124,6 +225,110 @@
   EXPECT_THAT(s.inner_member().uint32_member_2(), Eq(0));
 }
 
+TEST(MessageTest, MultipleOneofsSettersEnforceMutualExclusion) {
+  OneofTestMessageTP msg;
+
+  // Set field in oneof_1 (submessage)
+  msg.mutable_field_a()->set_uint32_member_1(10);
+  EXPECT_TRUE(msg.has_field_a());
+  EXPECT_EQ(msg.field_a().uint32_member_1(), 10);
+  EXPECT_FALSE(msg.has_field_b());
+  EXPECT_EQ(msg.my_oneof_1_case(), OneofTestMessageTP::kFieldA);
+
+  // Set field in oneof_2 (should be independent)
+  msg.set_field_c(30);
+  EXPECT_TRUE(msg.has_field_a());  // oneof_1 unaffected
+  EXPECT_TRUE(msg.has_field_c());
+  EXPECT_EQ(msg.field_c(), 30);
+  EXPECT_FALSE(msg.has_field_d());
+  EXPECT_EQ(msg.my_oneof_2_case(), OneofTestMessageTP::kFieldC);
+
+  // Mutually exclude within oneof_1
+  msg.set_field_b(20);
+  EXPECT_FALSE(msg.has_field_a());  // field_a cleared
+  EXPECT_TRUE(msg.has_field_b());
+  EXPECT_EQ(msg.field_b(), 20);
+  EXPECT_TRUE(msg.has_field_c());  // oneof_2 still unaffected
+  EXPECT_EQ(msg.my_oneof_1_case(), OneofTestMessageTP::kFieldB);
+
+  // Clear resets everything
+  msg.Clear();
+  EXPECT_FALSE(msg.has_field_a());
+  EXPECT_FALSE(msg.has_field_b());
+  EXPECT_FALSE(msg.has_field_c());
+  EXPECT_FALSE(msg.has_field_d());
+  EXPECT_EQ(msg.my_oneof_1_case(), OneofTestMessageTP::MY_ONEOF_1_NOT_SET);
+  EXPECT_EQ(msg.my_oneof_2_case(), OneofTestMessageTP::MY_ONEOF_2_NOT_SET);
+}
+
+TEST(MessageTest, MultipleOneofsParsingEnforcesMutualExclusionLastWins) {
+  // Serialized:
+  // oneof_1: field_a (submessage with member 1 = 10), then field_b (20) ->
+  // field_b wins oneof_2: field_c (30), then field_d (40) -> field_d wins
+  std::string bytes = absl::StrCat(
+      FieldWithNumber(1).IsSubMessage({FieldWithNumber(1).IsVarint(10)}),
+      FieldWithNumber(3).IsVarint(30), FieldWithNumber(2).IsVarint(20),
+      FieldWithNumber(4).IsVarint(40));
+
+  OneofTestMessageTP msg;
+  EXPECT_TRUE(msg.ParseFromString(bytes));
+
+  // Verify oneof_1 last-writer wins
+  EXPECT_FALSE(msg.has_field_a());
+  EXPECT_TRUE(msg.has_field_b());
+  EXPECT_EQ(msg.field_b(), 20);
+  EXPECT_EQ(msg.my_oneof_1_case(), OneofTestMessageTP::kFieldB);
+
+  // Verify oneof_2 last-writer wins
+  EXPECT_FALSE(msg.has_field_c());
+  EXPECT_TRUE(msg.has_field_d());
+  EXPECT_EQ(msg.field_d(), 40);
+  EXPECT_EQ(msg.my_oneof_2_case(), OneofTestMessageTP::kFieldD);
+}
+
+TEST(MessageTest, OneofParsingMergesSameField) {
+  // Serialized:
+  // oneof_1: field_a (member 1 = 10), then field_a again (member 2 = 20)
+  // Since it's the same field, they should merge!
+  std::string bytes = absl::StrCat(
+      FieldWithNumber(1).IsSubMessage({FieldWithNumber(1).IsVarint(10)}),
+      FieldWithNumber(1).IsSubMessage({FieldWithNumber(2).IsVarint(20)}));
+
+  OneofTestMessageTP msg;
+  EXPECT_TRUE(msg.ParseFromString(bytes));
+
+  EXPECT_TRUE(msg.has_field_a());
+  EXPECT_EQ(msg.field_a().uint32_member_1(), 10);
+  EXPECT_EQ(msg.field_a().uint32_member_2(), 20);
+  EXPECT_FALSE(msg.has_field_b());
+  EXPECT_EQ(msg.my_oneof_1_case(), OneofTestMessageTP::kFieldA);
+}
+
+TEST(MessageTest, OneofCopyConstructorWorks) {
+  OneofTestMessageTP msg1;
+  msg1.mutable_field_a()->set_uint32_member_1(10);
+  msg1.set_field_c(30);
+
+  // Copy construct
+  OneofTestMessageTP msg2 = msg1;
+  EXPECT_TRUE(msg2.has_field_a());
+  EXPECT_EQ(msg2.field_a().uint32_member_1(), 10);
+  EXPECT_TRUE(msg2.has_field_c());
+  EXPECT_EQ(msg2.field_c(), 30);
+  EXPECT_EQ(msg2.my_oneof_1_case(), OneofTestMessageTP::kFieldA);
+  EXPECT_EQ(msg2.my_oneof_2_case(), OneofTestMessageTP::kFieldC);
+
+  // Modify copy, original should be unaffected
+  msg2.set_field_b(20);
+  EXPECT_FALSE(msg2.has_field_a());
+  EXPECT_TRUE(msg2.has_field_b());
+  EXPECT_EQ(msg2.my_oneof_1_case(), OneofTestMessageTP::kFieldB);
+
+  EXPECT_TRUE(msg1.has_field_a());  // original still has field_a!
+  EXPECT_FALSE(msg1.has_field_b());
+  EXPECT_EQ(msg1.my_oneof_1_case(), OneofTestMessageTP::kFieldA);
+}
+
 #if !defined(TINK_CPP_SECRET_DATA_IS_STD_VECTOR)
 
 // Serializes a varint using a wrong CRC.