Mini table accessors Part2 (repeated fields).
Introduces upb_FieldValue for array accessor api.
PiperOrigin-RevId: 445491436
diff --git a/BUILD b/BUILD
index 6b57070..97545bf 100644
--- a/BUILD
+++ b/BUILD
@@ -160,6 +160,7 @@
copts = UPB_DEFAULT_COPTS,
visibility = ["//video/youtube/utils/elements/javascript/client/proto/upb/native:__pkg__"],
deps = [
+ ":collections",
":mini_table",
":mini_table_internal",
":port",
@@ -184,6 +185,7 @@
name = "mini_table_accessors_test",
srcs = ["upb/mini_table_accessors_test.cc"],
deps = [
+ ":collections",
":mini_table",
":mini_table_accessors",
":mini_table_internal",
diff --git a/upb/mini_table.h b/upb/mini_table.h
index d427b64..6c41f81 100644
--- a/upb/mini_table.h
+++ b/upb/mini_table.h
@@ -40,6 +40,11 @@
const upb_MiniTable_Field* upb_MiniTable_FindFieldByNumber(
const upb_MiniTable* table, uint32_t number);
+UPB_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
+ const upb_MiniTable* mini_table, const upb_MiniTable_Field* field) {
+ return mini_table->subs[field->submsg_index].submsg;
+}
+
UPB_INLINE bool upb_MiniTable_Enum_CheckValue(const upb_MiniTable_Enum* e,
int32_t val) {
uint32_t uval = (uint32_t)val;
diff --git a/upb/mini_table_accessors.c b/upb/mini_table_accessors.c
index 86f2f42..8a1b891 100644
--- a/upb/mini_table_accessors.c
+++ b/upb/mini_table_accessors.c
@@ -28,7 +28,6 @@
#include "upb/mini_table_accessors.h"
#include "upb/mini_table.h"
-#include "upb/mini_table_accessors_internal.h"
#include "upb/msg_internal.h"
// Must be last.
@@ -59,11 +58,6 @@
return upb_IsRepeatedOrMap(f) ? sizeof(void*) : sizes[f->descriptortype];
}
-UPB_INLINE upb_Message* upb_MiniTable_GetMessage(
- const upb_Message* msg, const upb_MiniTable_Field* field) {
- return UPB_PTR_AT(msg, field->offset, upb_Message);
-}
-
bool upb_MiniTable_HasField(const upb_Message* msg,
const upb_MiniTable_Field* field) {
if (_upb_MiniTable_Field_InOneOf(field)) {
diff --git a/upb/mini_table_accessors.h b/upb/mini_table_accessors.h
index d5279fe..dddaba6 100644
--- a/upb/mini_table_accessors.h
+++ b/upb/mini_table_accessors.h
@@ -28,6 +28,7 @@
#ifndef UPB_MINI_TABLE_ACCESSORS_H_
#define UPB_MINI_TABLE_ACCESSORS_H_
+#include "upb/collections.h"
#include "upb/mini_table_accessors_internal.h"
#include "upb/msg_internal.h"
@@ -38,36 +39,36 @@
extern "C" {
#endif
-bool upb_MiniTable_HasField(const upb_Message *msg,
- const upb_MiniTable_Field *field);
+bool upb_MiniTable_HasField(const upb_Message* msg,
+ const upb_MiniTable_Field* field);
-void upb_MiniTable_ClearField(upb_Message *msg,
- const upb_MiniTable_Field *field);
+void upb_MiniTable_ClearField(upb_Message* msg,
+ const upb_MiniTable_Field* field);
-UPB_INLINE bool upb_MiniTable_GetBool(const upb_Message *msg,
- const upb_MiniTable_Field *field) {
+UPB_INLINE bool upb_MiniTable_GetBool(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bool);
return *UPB_PTR_AT(msg, field->offset, bool);
}
-UPB_INLINE void upb_MiniTable_SetBool(upb_Message *msg,
- const upb_MiniTable_Field *field,
+UPB_INLINE void upb_MiniTable_SetBool(upb_Message* msg,
+ const upb_MiniTable_Field* field,
bool value) {
UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bool);
_upb_MiniTable_SetPresence(msg, field);
*UPB_PTR_AT(msg, field->offset, bool) = value;
}
-UPB_INLINE int32_t upb_MiniTable_GetInt32(const upb_Message *msg,
- const upb_MiniTable_Field *field) {
+UPB_INLINE int32_t upb_MiniTable_GetInt32(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int32 ||
field->descriptortype == kUpb_FieldType_SInt32 ||
field->descriptortype == kUpb_FieldType_SFixed32);
return *UPB_PTR_AT(msg, field->offset, int32_t);
}
-UPB_INLINE void upb_MiniTable_SetInt32(upb_Message *msg,
- const upb_MiniTable_Field *field,
+UPB_INLINE void upb_MiniTable_SetInt32(upb_Message* msg,
+ const upb_MiniTable_Field* field,
int32_t value) {
UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int32 ||
field->descriptortype == kUpb_FieldType_SInt32 ||
@@ -76,7 +77,151 @@
*UPB_PTR_AT(msg, field->offset, int32_t) = value;
}
-// TODO(ferhat): Add accessors for all proto field types.
+UPB_INLINE uint32_t upb_MiniTable_GetUInt32(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt32 ||
+ field->descriptortype == kUpb_FieldType_Fixed32);
+ return *UPB_PTR_AT(msg, field->offset, uint32_t);
+}
+
+UPB_INLINE void upb_MiniTable_SetUInt32(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ uint32_t value) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt32 ||
+ field->descriptortype == kUpb_FieldType_Fixed32);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, uint32_t) = value;
+}
+
+UPB_INLINE int32_t upb_MiniTable_GetEnum(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Enum);
+ return *UPB_PTR_AT(msg, field->offset, int32_t);
+}
+
+UPB_INLINE void upb_MiniTable_SetEnum(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ int32_t value) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Enum);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, int32_t) = value;
+}
+
+UPB_INLINE int64_t upb_MiniTable_GetInt64(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int64 ||
+ field->descriptortype == kUpb_FieldType_SInt64 ||
+ field->descriptortype == kUpb_FieldType_SFixed64);
+ return *UPB_PTR_AT(msg, field->offset, int64_t);
+}
+
+UPB_INLINE void upb_MiniTable_SetInt64(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ int64_t value) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int64 ||
+ field->descriptortype == kUpb_FieldType_SInt64 ||
+ field->descriptortype == kUpb_FieldType_SFixed64);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, int64_t) = value;
+}
+
+UPB_INLINE uint64_t upb_MiniTable_GetUInt64(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt64 ||
+ field->descriptortype == kUpb_FieldType_Fixed64);
+ return *UPB_PTR_AT(msg, field->offset, uint64_t);
+}
+
+UPB_INLINE void upb_MiniTable_SetUInt64(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ uint64_t value) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt64 ||
+ field->descriptortype == kUpb_FieldType_Fixed64);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, uint64_t) = value;
+}
+
+UPB_INLINE float upb_MiniTable_GetFloat(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Float);
+ return *UPB_PTR_AT(msg, field->offset, float);
+}
+
+UPB_INLINE void upb_MiniTable_SetFloat(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ float value) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Float);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, float) = value;
+}
+
+UPB_INLINE double upb_MiniTable_GetDouble(const upb_Message* msg,
+ const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Double);
+ return *UPB_PTR_AT(msg, field->offset, double);
+}
+
+UPB_INLINE void upb_MiniTable_SetDouble(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ double value) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Double);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, double) = value;
+}
+
+UPB_INLINE upb_StringView upb_MiniTable_GetString(
+ const upb_Message* msg, const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bytes ||
+ field->descriptortype == kUpb_FieldType_String);
+ return *UPB_PTR_AT(msg, field->offset, upb_StringView);
+}
+
+UPB_INLINE void upb_MiniTable_SetString(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ upb_StringView value) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bytes ||
+ field->descriptortype == kUpb_FieldType_String);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, upb_StringView) = value;
+}
+
+UPB_INLINE const upb_Message* upb_MiniTable_GetMessage(
+ const upb_Message* msg, const upb_MiniTable_Field* field) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message);
+ return *UPB_PTR_AT(msg, field->offset, const upb_Message*);
+}
+
+UPB_INLINE void upb_MiniTable_SetMessage(upb_Message* msg,
+ const upb_MiniTable_Field* field,
+ upb_Message* sub_message) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message);
+ _upb_MiniTable_SetPresence(msg, field);
+ *UPB_PTR_AT(msg, field->offset, const upb_Message*) = sub_message;
+}
+
+UPB_INLINE upb_Message* upb_MiniTable_GetMutableMessage(
+ upb_Message* msg, const upb_MiniTable* mini_table,
+ const upb_MiniTable_Field* field, upb_Arena* arena) {
+ UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message);
+ upb_Message* sub_message = *UPB_PTR_AT(msg, field->offset, upb_Message*);
+ if (!sub_message) {
+ sub_message =
+ _upb_Message_New(mini_table->subs[field->submsg_index].submsg, arena);
+ }
+ return sub_message;
+}
+
+UPB_INLINE const upb_Array* upb_MiniTable_GetArray(
+ const upb_Message* msg, const upb_MiniTable_Field* field) {
+ return (const upb_Array*)*UPB_PTR_AT(msg, field->offset, upb_Array*);
+}
+
+UPB_INLINE upb_Array* upb_MiniTable_GetMutableArray(
+ upb_Message* msg, const upb_MiniTable_Field* field) {
+ return (upb_Array*)*UPB_PTR_AT(msg, field->offset, upb_Array*);
+}
+
+// TODO(ferhat): Add support for extensions.
#ifdef __cplusplus
} /* extern "C" */
diff --git a/upb/mini_table_accessors_test.cc b/upb/mini_table_accessors_test.cc
index c2f84f4..04ac5c3 100644
--- a/upb/mini_table_accessors_test.cc
+++ b/upb/mini_table_accessors_test.cc
@@ -36,20 +36,35 @@
#include "gtest/gtest.h"
#include "src/google/protobuf/test_messages_proto2.upb.h"
#include "src/google/protobuf/test_messages_proto3.upb.h"
+#include "upb/collections.h"
#include "upb/mini_table.h"
namespace {
-// Proto Field numbers used for reflective access.
+// Proto2 test messages field numbers used for reflective access.
const uint32_t kFieldOptionalInt32 = 1;
+const uint32_t kFieldOptionalUInt32 = 3;
const uint32_t kFieldOptionalBool = 13;
const uint32_t kFieldOptionalString = 14;
const uint32_t kFieldOptionalNestedMessage = 18;
+const uint32_t kFieldOptionalRepeatedInt32 = 31;
+const uint32_t kFieldOptionalNestedMessageA = 1;
const uint32_t kFieldOptionalOneOfUInt32 = 111;
const uint32_t kFieldOptionalOneOfString = 113;
-const char kTestStr1[] = "Hello";
+const uint32_t kFieldProto3OptionalInt64 = 2;
+const uint32_t kFieldProto3OptionalUInt64 = 4;
+
+const char kTestStr1[] = "Hello1";
+const char kTestStr2[] = "Hello2";
const int32_t kTestInt32 = 567;
+const int32_t kTestUInt32 = 0xF1234567;
+const uint64_t kTestUInt64 = 0xFEDCBAFF87654321;
+
+const upb_MiniTable_Field* find_proto3_field(int field_number) {
+ return upb_MiniTable_FindFieldByNumber(
+ &protobuf_test_messages_proto3_TestAllTypesProto3_msginit, field_number);
+}
const upb_MiniTable_Field* find_proto2_field(int field_number) {
return upb_MiniTable_FindFieldByNumber(
@@ -148,6 +163,196 @@
kTestInt32,
protobuf_test_messages_proto2_TestAllTypesProto2_optional_int32(msg));
+ const upb_MiniTable_Field* optional_uint32_field =
+ find_proto2_field(kFieldOptionalUInt32);
+
+ EXPECT_EQ(
+ 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg));
+ EXPECT_EQ(0, upb_MiniTable_GetUInt32(msg, optional_uint32_field));
+ upb_MiniTable_SetUInt32(msg, optional_uint32_field, kTestUInt32);
+ EXPECT_EQ(kTestUInt32, upb_MiniTable_GetUInt32(msg, optional_uint32_field));
+ EXPECT_EQ(
+ kTestUInt32,
+ protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg));
+
+ upb_Arena_Free(arena);
+}
+
+TEST(GeneratedCode, ScalarProto3) {
+ upb_Arena* arena = upb_Arena_New();
+ protobuf_test_messages_proto3_TestAllTypesProto3* msg =
+ protobuf_test_messages_proto3_TestAllTypesProto3_new(arena);
+
+ const upb_MiniTable_Field* optional_int64_field =
+ find_proto3_field(kFieldProto3OptionalInt64);
+ const upb_MiniTable_Field* optional_uint64_field =
+ find_proto3_field(kFieldProto3OptionalUInt64);
+
+ EXPECT_EQ(
+ 0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(msg));
+ upb_MiniTable_SetInt64(msg, optional_int64_field, -1);
+ EXPECT_EQ(
+ -1, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(msg));
+ EXPECT_EQ(-1, upb_MiniTable_GetInt64(msg, optional_int64_field));
+
+ EXPECT_EQ(
+ 0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg));
+ upb_MiniTable_SetUInt64(msg, optional_uint64_field, kTestUInt64);
+ EXPECT_EQ(
+ kTestUInt64,
+ protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg));
+ EXPECT_EQ(kTestUInt64, upb_MiniTable_GetUInt64(msg, optional_uint64_field));
+
+ upb_Arena_Free(arena);
+}
+
+TEST(GeneratedCode, Strings) {
+ upb_Arena* arena = upb_Arena_New();
+ protobuf_test_messages_proto2_TestAllTypesProto2* msg =
+ protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
+
+ const upb_MiniTable_Field* optional_string_field =
+ find_proto2_field(kFieldOptionalString);
+
+ // Test default.
+ EXPECT_EQ(false, upb_MiniTable_HasField(msg, optional_string_field));
+ // Test read after write using C.
+ protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_string(
+ msg, upb_StringView_FromString(kTestStr1));
+ EXPECT_EQ(true, upb_MiniTable_HasField(msg, optional_string_field));
+ upb_StringView value = upb_MiniTable_GetString(msg, optional_string_field);
+ std::string read_value = std::string(value.data, value.size);
+ EXPECT_EQ(kTestStr1, read_value);
+ // Clear.
+ upb_MiniTable_ClearField(msg, optional_string_field);
+ EXPECT_EQ(false, upb_MiniTable_HasField(msg, optional_string_field));
+ EXPECT_EQ(
+ false,
+ protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string(
+ msg));
+ upb_MiniTable_SetString(msg, optional_string_field,
+ upb_StringView_FromString(kTestStr2));
+ EXPECT_EQ(true, upb_MiniTable_HasField(msg, optional_string_field));
+ EXPECT_EQ(
+ true,
+ protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string(
+ msg));
+ value = protobuf_test_messages_proto2_TestAllTypesProto2_optional_string(msg);
+ read_value = std::string(value.data, value.size);
+ EXPECT_EQ(kTestStr2, read_value);
+
+ upb_Arena_Free(arena);
+}
+
+TEST(GeneratedCode, SubMessage) {
+ upb_Arena* arena = upb_Arena_New();
+ protobuf_test_messages_proto2_TestAllTypesProto2* msg =
+ protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
+
+ const upb_MiniTable_Field* optional_message_field =
+ find_proto2_field(kFieldOptionalNestedMessage);
+
+ const upb_Message* test_message =
+ upb_MiniTable_GetMessage(msg, optional_message_field);
+ EXPECT_EQ(NULL, test_message);
+
+ EXPECT_EQ(false, upb_MiniTable_HasField(msg, optional_message_field));
+
+ // Get mutable using C API.
+ protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* nested_message =
+ protobuf_test_messages_proto2_TestAllTypesProto2_mutable_optional_nested_message(
+ msg, arena);
+ EXPECT_EQ(true, nested_message != nullptr);
+ EXPECT_EQ(true, upb_MiniTable_HasField(msg, optional_message_field));
+ protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(
+ nested_message, 5);
+
+ // Read back using mini table API.
+ const upb_Message* sub_message =
+ upb_MiniTable_GetMessage(msg, optional_message_field);
+ EXPECT_EQ(true, sub_message != NULL);
+
+ const upb_MiniTable_Field* nested_message_a_field =
+ upb_MiniTable_FindFieldByNumber(
+ &protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_msginit,
+ kFieldOptionalNestedMessageA);
+ EXPECT_EQ(5, upb_MiniTable_GetInt32(sub_message, nested_message_a_field));
+
+ upb_MiniTable_ClearField(msg, optional_message_field);
+ EXPECT_EQ(
+ NULL,
+ protobuf_test_messages_proto2_TestAllTypesProto2_optional_nested_message(
+ msg));
+ EXPECT_EQ(false, upb_MiniTable_HasField(msg, optional_message_field));
+
+ upb_Message* new_nested_message =
+ protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new(arena);
+ upb_MiniTable_SetInt32(new_nested_message, nested_message_a_field, 123);
+ upb_MiniTable_SetMessage(msg, optional_message_field, new_nested_message);
+
+ upb_Message* mutable_message = upb_MiniTable_GetMutableMessage(
+ msg, &protobuf_test_messages_proto2_TestAllTypesProto2_msginit,
+ optional_message_field, arena);
+ EXPECT_EQ(
+ true,
+ protobuf_test_messages_proto2_TestAllTypesProto2_optional_nested_message(
+ msg) != NULL);
+ EXPECT_EQ(true, upb_MiniTable_HasField(msg, optional_message_field));
+ EXPECT_EQ(123,
+ upb_MiniTable_GetInt32(mutable_message, nested_message_a_field));
+
+ upb_Arena_Free(arena);
+}
+
+TEST(GeneratedCode, RepeatedScalar) {
+ upb_Arena* arena = upb_Arena_New();
+ protobuf_test_messages_proto2_TestAllTypesProto2* msg =
+ protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
+
+ const upb_MiniTable_Field* repeated_int32_field =
+ find_proto2_field(kFieldOptionalRepeatedInt32);
+
+ size_t len;
+ const int32_t* arr =
+ protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg,
+ &len);
+ // Test Get/Set Array values, validate with C API.
+ EXPECT_EQ(0, len);
+ EXPECT_EQ(NULL, arr);
+ EXPECT_EQ(NULL, upb_MiniTable_GetArray(msg, repeated_int32_field));
+ protobuf_test_messages_proto2_TestAllTypesProto2_resize_repeated_int32(
+ msg, 10, arena);
+ int32_t* mutable_values =
+ protobuf_test_messages_proto2_TestAllTypesProto2_mutable_repeated_int32(
+ msg, &len);
+ mutable_values[5] = 123;
+ const upb_Array* readonly_arr =
+ upb_MiniTable_GetArray(msg, repeated_int32_field);
+ EXPECT_EQ(123, upb_Array_Get(readonly_arr, 5).int32_val);
+
+ upb_MessageValue new_value;
+ new_value.int32_val = 567;
+ upb_Array* mutable_array =
+ upb_MiniTable_GetMutableArray(msg, repeated_int32_field);
+ upb_Array_Set(mutable_array, 5, new_value);
+ EXPECT_EQ(new_value.int32_val,
+ protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(
+ msg, &len)[5]);
+
+ // Test resize.
+ bool result = upb_Array_Resize(mutable_array, 20, arena);
+ EXPECT_EQ(true, result);
+ upb_Array_Set(mutable_array, 19, new_value);
+ EXPECT_EQ(new_value.int32_val,
+ protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(
+ msg, &len)[19]);
+ upb_Array_Resize(mutable_array, 0, arena);
+ const int32_t* zero_length_array =
+ protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg,
+ &len);
+ EXPECT_EQ(0, len);
+ EXPECT_EQ(true, zero_length_array != NULL);
+
upb_Arena_Free(arena);
}