Add upb_Message_ClearOneof (and retain upb_Message_WhichOneofFieldNumber)
upb users currently need to manually fetch a oneof field in order to clear it.
In this CL, we add a convenience method to do that in one fell swoop.
PiperOrigin-RevId: 631454136
diff --git a/upb/message/accessors.h b/upb/message/accessors.h
index c2af8df..c50467c 100644
--- a/upb/message/accessors.h
+++ b/upb/message/accessors.h
@@ -54,6 +54,10 @@
UPB_API_INLINE void upb_Message_ClearExtension(upb_Message* msg,
const upb_MiniTableExtension* e);
+UPB_API_INLINE void upb_Message_ClearOneof(upb_Message* msg,
+ const upb_MiniTable* m,
+ const upb_MiniTableField* f);
+
UPB_API_INLINE bool upb_Message_HasBaseField(const upb_Message* msg,
const upb_MiniTableField* f);
diff --git a/upb/message/accessors_test.cc b/upb/message/accessors_test.cc
index 5b0dd36..b6d8d42 100644
--- a/upb/message/accessors_test.cc
+++ b/upb/message/accessors_test.cc
@@ -478,4 +478,28 @@
upb_Arena_Free(arena);
}
+TEST(GeneratedCode, OneofClear) {
+ upb_Arena* arena = upb_Arena_New();
+
+ protobuf_test_messages_proto2_TestAllTypesProto2* msg =
+ protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
+
+ const upb_MiniTable* table =
+ &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init;
+
+ // oneof_uint32
+ const upb_MiniTableField* oneofField =
+ upb_MiniTable_FindFieldByNumber(table, 111);
+ EXPECT_TRUE(upb_MiniTableField_IsInOneof(oneofField));
+ protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_uint32(msg, 522);
+ EXPECT_TRUE(
+ protobuf_test_messages_proto2_TestAllTypesProto2_has_oneof_uint32(msg));
+
+ upb_Message_ClearOneof((upb_Message*)msg, table, oneofField);
+ EXPECT_FALSE(
+ protobuf_test_messages_proto2_TestAllTypesProto2_has_oneof_uint32(msg));
+
+ upb_Arena_Free(arena);
+}
+
} // namespace
diff --git a/upb/message/internal/accessors.h b/upb/message/internal/accessors.h
index a6c0722..c7b447e 100644
--- a/upb/message/internal/accessors.h
+++ b/upb/message/internal/accessors.h
@@ -693,6 +693,21 @@
}
}
+UPB_API_INLINE void upb_Message_ClearOneof(struct upb_Message* msg,
+ const upb_MiniTable* m,
+ const upb_MiniTableField* f) {
+ UPB_ASSERT(!upb_Message_IsFrozen(msg));
+ uint32_t field_number = upb_Message_WhichOneofFieldNumber(msg, f);
+ if (field_number == 0) {
+ // No field in the oneof is set.
+ return;
+ }
+
+ const upb_MiniTableField* field =
+ upb_MiniTable_FindFieldByNumber(m, field_number);
+ upb_Message_ClearBaseField(msg, field);
+}
+
UPB_API_INLINE void* upb_Message_ResizeArrayUninitialized(
struct upb_Message* msg, const upb_MiniTableField* f, size_t size,
upb_Arena* arena) {