Mini table accessors Part2 (repeated fields).

Introduces upb_FieldValue for array accessor api.

PiperOrigin-RevId: 445491436
pull/13171/head
Protobuf Team 3 years ago committed by Copybara-Service
parent fbcd42b9f0
commit c7620a4690
  1. 2
      BUILD
  2. 5
      upb/mini_table.h
  3. 6
      upb/mini_table_accessors.c
  4. 171
      upb/mini_table_accessors.h
  5. 209
      upb/mini_table_accessors_test.cc

@ -160,6 +160,7 @@ cc_library(
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 @@ cc_test(
name = "mini_table_accessors_test",
srcs = ["upb/mini_table_accessors_test.cc"],
deps = [
":collections",
":mini_table",
":mini_table_accessors",
":mini_table_internal",

@ -40,6 +40,11 @@ extern "C" {
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;

@ -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 @@ size_t upb_MiniTable_Field_GetSize(const upb_MiniTable_Field* f) {
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)) {

@ -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_INLINE void upb_MiniTable_SetInt32(upb_Message *msg,
*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" */

@ -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 @@ TEST(GeneratedCode, ScalarsProto2) {
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);
}

Loading…
Cancel
Save