Unified all hazzers to use MiniTable accessors

This required some work to unify map entry messages with regular messages, with respect to presence.  Before map entry fields could never have presence.  Now they can have presence according to normal rules.  Note that this only applies to times that the user constructs a map entry directly.

PiperOrigin-RevId: 490611656
pull/13171/head
Joshua Haberman 2 years ago committed by Copybara-Service
parent e567b7c206
commit 9c6223c058
  1. 2
      BUILD
  2. 4
      upb/collections/map_sorter_internal.h
  3. 40
      upb/message/accessors.h
  4. 15
      upb/message/internal.h
  5. 9
      upb/mini_table/common.h
  6. 47
      upb/mini_table/decode.c
  7. 4
      upb/mini_table/encode.c
  8. 3
      upb/mini_table/encode_internal.h
  9. 4
      upb/mini_table/encode_internal.hpp
  10. 26
      upb/mini_table/message_internal.h
  11. 64
      upb/reflection/message.c
  12. 16
      upb/reflection/message_def.c
  13. 4
      upb/text/encode.c
  14. 14
      upb/wire/decode.c
  15. 8
      upb/wire/encode.c
  16. 8
      upbc/file_layout.cc
  17. 35
      upbc/protoc-gen-upb.cc

@ -228,6 +228,7 @@ cc_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":base", ":base",
":hash",
":mem", ":mem",
":port", ":port",
], ],
@ -576,6 +577,7 @@ cc_library(
":collections", ":collections",
":descriptor_upb_proto", ":descriptor_upb_proto",
":hash", ":hash",
":message_accessors",
":mini_table_internal", ":mini_table_internal",
":port", ":port",
":upb", ":upb",

@ -71,9 +71,9 @@ UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
if (sorted->pos == sorted->end) return false; if (sorted->pos == sorted->end) return false;
const upb_tabent* tabent = s->entries[sorted->pos++]; const upb_tabent* tabent = s->entries[sorted->pos++];
upb_StringView key = upb_tabstrview(tabent->key); upb_StringView key = upb_tabstrview(tabent->key);
_upb_map_fromkey(key, &ent->k, map->key_size); _upb_map_fromkey(key, &ent->data.k, map->key_size);
upb_value val = {tabent->val.val}; upb_value val = {tabent->val.val};
_upb_map_fromvalue(val, &ent->v, map->val_size); _upb_map_fromvalue(val, &ent->data.v, map->val_size);
return true; return true;
} }

@ -68,8 +68,8 @@ UPB_INLINE void _upb_MiniTable_SetPresence(upb_Message* msg,
UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg, UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg,
const upb_MiniTableField* field); const upb_MiniTableField* field);
UPB_INLINE bool _upb_MiniTable_DefaultIsNonZero( UPB_INLINE bool _upb_MiniTable_ValueIsNonZero(const void* default_val,
const void* default_val, const upb_MiniTableField* field) { const upb_MiniTableField* field) {
char zero[16] = {0}; char zero[16] = {0};
switch (_upb_MiniTableField_GetRep(field)) { switch (_upb_MiniTableField_GetRep(field)) {
case kUpb_FieldRep_1Byte: case kUpb_FieldRep_1Byte:
@ -139,7 +139,7 @@ static UPB_FORCEINLINE void _upb_MiniTable_GetNonExtensionField(
const void* default_val, void* val) { const void* default_val, void* val) {
UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
if ((_upb_MiniTableField_InOneOf(field) || if ((_upb_MiniTableField_InOneOf(field) ||
_upb_MiniTable_DefaultIsNonZero(default_val, field)) && _upb_MiniTable_ValueIsNonZero(default_val, field)) &&
!upb_MiniTable_HasField(msg, field)) { !upb_MiniTable_HasField(msg, field)) {
_upb_MiniTable_CopyFieldData(val, default_val, field); _upb_MiniTable_CopyFieldData(val, default_val, field);
return; return;
@ -201,6 +201,33 @@ UPB_INLINE bool _upb_MiniTable_SetField(upb_Message* msg,
} }
} }
UPB_INLINE bool _upb_MiniTable_HasExtensionField(
const upb_Message* msg, const upb_MiniTableExtension* ext) {
UPB_ASSERT(upb_MiniTableField_HasPresence(&ext->field));
return _upb_Message_Getext(msg, ext) != NULL;
}
UPB_INLINE bool _upb_MiniTable_HasNonExtensionField(
const upb_Message* msg, const upb_MiniTableField* field) {
UPB_ASSERT(upb_MiniTableField_HasPresence(field));
UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
if (_upb_MiniTableField_InOneOf(field)) {
return _upb_getoneofcase_field(msg, field) == field->number;
} else {
return _upb_hasbit_field(msg, field);
}
}
UPB_INLINE bool _upb_MiniTable_HasField(const upb_Message* msg,
const upb_MiniTableField* field) {
if (upb_MiniTableField_IsExtension(field)) {
return _upb_MiniTable_HasExtensionField(
msg, (const upb_MiniTableExtension*)field);
} else {
return _upb_MiniTable_HasNonExtensionField(msg, field);
}
}
// EVERYTHING ABOVE THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// // EVERYTHING ABOVE THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
void upb_MiniTable_ClearField(upb_Message* msg, void upb_MiniTable_ClearField(upb_Message* msg,
@ -208,12 +235,7 @@ void upb_MiniTable_ClearField(upb_Message* msg,
UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg, UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg,
const upb_MiniTableField* field) { const upb_MiniTableField* field) {
if (_upb_MiniTableField_InOneOf(field)) { return _upb_MiniTable_HasNonExtensionField(msg, field);
return _upb_getoneofcase_field(msg, field) == field->number;
}
UPB_ASSERT(field->presence > 0);
return _upb_hasbit_field(msg, field);
} }
UPB_INLINE bool upb_MiniTable_GetBool(const upb_Message* msg, UPB_INLINE bool upb_MiniTable_GetBool(const upb_Message* msg,

@ -126,21 +126,6 @@ void _upb_Message_DiscardUnknown_shallow(upb_Message* msg);
bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len, bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
upb_Arena* arena); upb_Arena* arena);
/* Map entries aren't actually stored, they are only used during parsing. For
* parsing, it helps a lot if all map entry messages have the same layout.
* The compiler and def.c must ensure that all map entries have this layout. */
typedef struct {
upb_Message_Internal internal;
union {
upb_StringView str; /* For str/bytes. */
upb_value val; /* For all other types. */
} k;
union {
upb_StringView str; /* For str/bytes. */
upb_value val; /* For all other types. */
} v;
} upb_MapEntry;
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

@ -63,6 +63,15 @@ UPB_INLINE bool upb_MiniTableField_IsExtension(
return field->mode & kUpb_LabelFlags_IsExtension; return field->mode & kUpb_LabelFlags_IsExtension;
} }
UPB_INLINE bool upb_MiniTableField_HasPresence(
const upb_MiniTableField* field) {
if (upb_MiniTableField_IsExtension(field)) {
return !upb_IsRepeatedOrMap(field);
} else {
return field->presence != 0;
}
}
UPB_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( UPB_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
const upb_MiniTable* mini_table, const upb_MiniTableField* field) { const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
return mini_table->subs[field->submsg_index].submsg; return mini_table->subs[field->submsg_index].submsg;

@ -663,40 +663,6 @@ static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) {
d->table->size = UPB_ALIGN_UP(d->table->size, 8); d->table->size = UPB_ALIGN_UP(d->table->size, 8);
} }
static void upb_MiniTable_BuildMapEntry(upb_MtDecoder* d, char key_type,
char val_type) {
upb_MiniTableField* fields = upb_Arena_Malloc(d->arena, sizeof(*fields) * 2);
if (!fields) {
upb_MtDecoder_ErrorFormat(d, "OOM while building map mini table field");
UPB_UNREACHABLE();
}
size_t field_size =
upb_MtDecoder_SizeOfRep(kUpb_FieldRep_StringView, d->platform);
uint32_t sub_count = 0;
fields[0].number = 1;
fields[1].number = 2;
upb_MiniTable_SetField(d, key_type, &fields[0], 0, &sub_count);
upb_MiniTable_SetField(d, val_type, &fields[1], 0, &sub_count);
upb_MtDecoder_AllocateSubs(d, sub_count);
// Map entries have a pre-determined layout, regardless of types.
fields[0].presence = 0;
fields[1].presence = 0;
fields[0].offset = 0;
fields[1].offset = field_size;
upb_MiniTable* ret = d->table;
ret->size = UPB_ALIGN_UP(2 * field_size, 8);
ret->field_count = 2;
ret->ext = kUpb_ExtMode_NonExtendable | kUpb_ExtMode_IsMapEntry;
ret->dense_below = 2;
ret->table_mask = -1;
ret->required_count = 0;
ret->fields = fields;
}
static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data, static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data,
size_t len) { size_t len) {
if (len < 2) { if (len < 2) {
@ -723,7 +689,18 @@ static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data,
upb_MtDecoder_ErrorFormat(d, "Invalid map key field type: %d", key_type); upb_MtDecoder_ErrorFormat(d, "Invalid map key field type: %d", key_type);
UPB_UNREACHABLE(); UPB_UNREACHABLE();
} }
upb_MiniTable_BuildMapEntry(d, data[0], data[1]);
upb_MtDecoder_ParseMessage(d, data, len);
upb_MtDecoder_AssignHasbits(d->table);
// Map entries have a pre-determined layout, regardless of types.
d->fields[0].offset = offsetof(upb_MapEntryData, k);
d->fields[1].offset = offsetof(upb_MapEntryData, v);
d->table->size = UPB_ALIGN_UP(sizeof(upb_MapEntryData), 8);
// Map entries have a special bit set to signal it's a map entry, used in
// upb_MiniTable_SetSubMessage() below.
d->table->ext |= kUpb_ExtMode_IsMapEntry;
} }
static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data, static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data,

@ -120,7 +120,7 @@ char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr,
char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr, char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr,
upb_FieldType key_type, upb_FieldType key_type,
upb_FieldType value_type, upb_FieldType value_type, uint64_t key_mod,
uint64_t value_mod) { uint64_t value_mod) {
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
in->state.msg_state.msg_modifiers = 0; in->state.msg_state.msg_modifiers = 0;
@ -130,7 +130,7 @@ char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr,
ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MapV1); ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MapV1);
if (!ptr) return NULL; if (!ptr) return NULL;
ptr = upb_MtDataEncoder_PutField(e, ptr, key_type, 1, 0); ptr = upb_MtDataEncoder_PutField(e, ptr, key_type, 1, key_mod);
if (!ptr) return NULL; if (!ptr) return NULL;
return upb_MtDataEncoder_PutField(e, ptr, value_type, 2, value_mod); return upb_MtDataEncoder_PutField(e, ptr, value_type, 2, value_mod);

@ -95,7 +95,8 @@ char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr,
// Encodes an entire mini descriptor for a map. // Encodes an entire mini descriptor for a map.
char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr, char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr,
upb_FieldType key_type, upb_FieldType key_type,
upb_FieldType value_type, uint64_t value_mod); upb_FieldType value_type, uint64_t key_mod,
uint64_t value_mod);
// Encodes an entire mini descriptor for a message set. // Encodes an entire mini descriptor for a message set.
char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr); char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr);

@ -89,10 +89,10 @@ class MtDataEncoder {
} }
bool EncodeMap(upb_FieldType key_type, upb_FieldType val_type, bool EncodeMap(upb_FieldType key_type, upb_FieldType val_type,
uint64_t val_mod) { uint64_t key_mod, uint64_t val_mod) {
return appender_([=](char* buf) { return appender_([=](char* buf) {
return upb_MtDataEncoder_EncodeMap(&encoder_, buf, key_type, val_type, return upb_MtDataEncoder_EncodeMap(&encoder_, buf, key_type, val_type,
val_mod); key_mod, val_mod);
}); });
} }

@ -28,6 +28,8 @@
#ifndef UPB_MINI_TABLE_MESSAGE_INTERNAL_H_ #ifndef UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
#define UPB_MINI_TABLE_MESSAGE_INTERNAL_H_ #define UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
#include "upb/base/string_view.h"
#include "upb/hash/common.h"
#include "upb/mini_table/types.h" #include "upb/mini_table/types.h"
// Must be last. // Must be last.
@ -77,6 +79,30 @@ struct upb_MiniTable {
_upb_FastTable_Entry fasttable[]; _upb_FastTable_Entry fasttable[];
}; };
// Map entries aren't actually stored for map fields, they are only used during
// parsing. For parsing, it helps a lot if all map entry messages have the same
// layout. The layout code in mini_table/decode.c will ensure that all map
// entries have this layout.
//
// Note that users can and do create map entries directly, which will also use
// this layout.
typedef struct {
uint32_t hasbits;
union {
upb_StringView str; // For str/bytes.
upb_value val; // For all other types.
} k;
union {
upb_StringView str; // For str/bytes.
upb_value val; // For all other types.
} v;
} upb_MapEntryData;
typedef struct {
void* internal_data;
upb_MapEntryData data;
} upb_MapEntry;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

@ -31,7 +31,9 @@
#include "upb/collections/map.h" #include "upb/collections/map.h"
#include "upb/hash/common.h" #include "upb/hash/common.h"
#include "upb/message/accessors.h"
#include "upb/message/message.h" #include "upb/message/message.h"
#include "upb/mini_table/field_internal.h"
#include "upb/reflection/def.h" #include "upb/reflection/def.h"
#include "upb/reflection/def_pool.h" #include "upb/reflection/def_pool.h"
#include "upb/reflection/def_type.h" #include "upb/reflection/def_type.h"
@ -71,32 +73,9 @@ static bool in_oneof(const upb_MiniTableField* field) {
return field->presence < 0; return field->presence < 0;
} }
static upb_MessageValue _upb_Message_Getraw(const upb_Message* msg,
const upb_FieldDef* f) {
const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
const char* mem = UPB_PTR_AT(msg, field->offset, char);
upb_MessageValue val = {0};
memcpy(&val, mem, get_field_size(field));
return val;
}
bool upb_Message_Has(const upb_Message* msg, const upb_FieldDef* f) { bool upb_Message_Has(const upb_Message* msg, const upb_FieldDef* f) {
assert(upb_FieldDef_HasPresence(f)); UPB_ASSERT(upb_FieldDef_HasPresence(f));
if (upb_FieldDef_IsExtension(f)) { return _upb_MiniTable_HasField(msg, upb_FieldDef_MiniTable(f));
const upb_MiniTableExtension* ext = _upb_FieldDef_ExtensionMiniTable(f);
return _upb_Message_Getext(msg, ext) != NULL;
} else {
const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
if (in_oneof(field)) {
return _upb_getoneofcase_field(msg, field) == field->number;
} else if (field->presence > 0) {
return _upb_hasbit_field(msg, field);
} else {
UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message ||
field->descriptortype == kUpb_FieldType_Group);
return _upb_Message_Getraw(msg, f).msg_val != NULL;
}
}
} }
const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg, const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg,
@ -194,31 +173,28 @@ bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
upb_MessageValue* out_val, size_t* iter) { upb_MessageValue* out_val, size_t* iter) {
size_t i = *iter; size_t i = *iter;
size_t n = upb_MessageDef_FieldCount(m); size_t n = upb_MessageDef_FieldCount(m);
const upb_MessageValue zero = {0};
UPB_UNUSED(ext_pool); UPB_UNUSED(ext_pool);
/* Iterate over normal fields, returning the first one that is set. */ // Iterate over normal fields, returning the first one that is set.
while (++i < n) { while (++i < n) {
const upb_FieldDef* f = upb_MessageDef_Field(m, i); const upb_FieldDef* f = upb_MessageDef_Field(m, i);
upb_MessageValue val = _upb_Message_Getraw(msg, f); const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
upb_MessageValue val = upb_Message_Get(msg, f);
/* Skip field if unset or empty. */ // Skip field if unset or empty.
if (upb_FieldDef_HasPresence(f)) { if (upb_MiniTableField_HasPresence(field)) {
if (!upb_Message_Has(msg, f)) continue; if (!upb_Message_Has(msg, f)) continue;
} else { } else {
upb_MessageValue test = val; switch (upb_FieldMode_Get(field)) {
if (upb_FieldDef_IsString(f) && !upb_FieldDef_IsRepeated(f)) { case kUpb_FieldMode_Map:
/* Clear string pointer, only size matters (ptr could be non-NULL). */ if (!val.map_val || upb_Map_Size(val.map_val) == 0) continue;
test.str_val.data = NULL; break;
} case kUpb_FieldMode_Array:
/* Continue if NULL or 0. */ if (!val.array_val || upb_Array_Size(val.array_val) == 0) continue;
if (memcmp(&test, &zero, sizeof(test)) == 0) continue; break;
case kUpb_FieldMode_Scalar:
/* Continue on empty array or map. */ if (!_upb_MiniTable_ValueIsNonZero(&val, field)) continue;
if (upb_FieldDef_IsMap(f)) { break;
if (upb_Map_Size(test.map_val) == 0) continue;
} else if (upb_FieldDef_IsRepeated(f)) {
if (upb_Array_Size(test.array_val) == 0) continue;
} }
} }
@ -229,7 +205,7 @@ bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
} }
if (ext_pool) { if (ext_pool) {
/* Return any extensions that are set. */ // Return any extensions that are set.
size_t count; size_t count;
const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &count); const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &count);
if (i - n < count) { if (i - n < count) {

@ -28,6 +28,7 @@
#include "upb/hash/int_table.h" #include "upb/hash/int_table.h"
#include "upb/hash/str_table.h" #include "upb/hash/str_table.h"
#include "upb/mini_table/decode.h" #include "upb/mini_table/decode.h"
#include "upb/reflection/def.h"
#include "upb/reflection/def_builder_internal.h" #include "upb/reflection/def_builder_internal.h"
#include "upb/reflection/def_type.h" #include "upb/reflection/def_type.h"
#include "upb/reflection/desc_state_internal.h" #include "upb/reflection/desc_state_internal.h"
@ -352,6 +353,7 @@ static upb_MiniTable* _upb_MessageDef_MakeMiniTable(upb_DefBuilder* ctx,
desc.data, desc.size, kUpb_MiniTablePlatform_Native, ctx->arena, desc.data, desc.size, kUpb_MiniTablePlatform_Native, ctx->arena,
scratch_data, scratch_size, ctx->status); scratch_data, scratch_size, ctx->status);
if (!ret) _upb_DefBuilder_FailJmp(ctx); if (!ret) _upb_DefBuilder_FailJmp(ctx);
return ret; return ret;
} }
@ -373,6 +375,8 @@ void _upb_MessageDef_Resolve(upb_DefBuilder* ctx, upb_MessageDef* m) {
UPB_ASSERT(layout_index < m->layout->field_count); UPB_ASSERT(layout_index < m->layout->field_count);
const upb_MiniTableField* mt_f = &m->layout->fields[layout_index]; const upb_MiniTableField* mt_f = &m->layout->fields[layout_index];
UPB_ASSERT(upb_FieldDef_Type(f) == upb_MiniTableField_Type(mt_f)); UPB_ASSERT(upb_FieldDef_Type(f) == upb_MiniTableField_Type(mt_f));
UPB_ASSERT(upb_FieldDef_HasPresence(f) ==
upb_MiniTableField_HasPresence(mt_f));
} }
#endif #endif
@ -490,15 +494,9 @@ static bool _upb_MessageDef_EncodeMap(upb_DescState* s, const upb_MessageDef* m,
UPB_ASSERT(_upb_FieldDef_LayoutIndex(key_field) == 0); UPB_ASSERT(_upb_FieldDef_LayoutIndex(key_field) == 0);
UPB_ASSERT(_upb_FieldDef_LayoutIndex(val_field) == 1); UPB_ASSERT(_upb_FieldDef_LayoutIndex(val_field) == 1);
const upb_FieldType key_type = upb_FieldDef_Type(key_field); s->ptr = upb_MtDataEncoder_EncodeMap(
const upb_FieldType val_type = upb_FieldDef_Type(val_field); &s->e, s->ptr, upb_FieldDef_Type(key_field), upb_FieldDef_Type(val_field),
_upb_FieldDef_Modifiers(key_field), _upb_FieldDef_Modifiers(val_field));
const uint64_t val_mod = _upb_FieldDef_IsClosedEnum(val_field)
? kUpb_FieldModifier_IsClosedEnum
: 0;
s->ptr =
upb_MtDataEncoder_EncodeMap(&s->e, s->ptr, key_type, val_type, val_mod);
return true; return true;
} }

@ -295,8 +295,8 @@ static void txtenc_map(txtenc* e, const upb_Map* map, const upb_FieldDef* f) {
_upb_mapsorter_pushmap(&e->sorter, upb_FieldDef_Type(key_f), map, &sorted); _upb_mapsorter_pushmap(&e->sorter, upb_FieldDef_Type(key_f), map, &sorted);
while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) { while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
upb_MessageValue key, val; upb_MessageValue key, val;
memcpy(&key, &ent.k, sizeof(key)); memcpy(&key, &ent.data.k, sizeof(key));
memcpy(&val, &ent.v, sizeof(val)); memcpy(&val, &ent.data.v, sizeof(val));
txtenc_mapentry(e, key, val, f); txtenc_mapentry(e, key, val, f);
} }
_upb_mapsorter_popmap(&e->sorter, &sorted); _upb_mapsorter_popmap(&e->sorter, &sorted);

@ -578,8 +578,8 @@ upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d, const upb_MiniTable* entry) {
const upb_MiniTableField* val_field = &entry->fields[1]; const upb_MiniTableField* val_field = &entry->fields[1];
char key_size = kSizeInMap[key_field->descriptortype]; char key_size = kSizeInMap[key_field->descriptortype];
char val_size = kSizeInMap[val_field->descriptortype]; char val_size = kSizeInMap[val_field->descriptortype];
UPB_ASSERT(key_field->offset == 0); UPB_ASSERT(key_field->offset == offsetof(upb_MapEntryData, k));
UPB_ASSERT(val_field->offset == sizeof(upb_StringView)); UPB_ASSERT(val_field->offset == offsetof(upb_MapEntryData, v));
upb_Map* ret = _upb_Map_New(&d->arena, key_size, val_size); upb_Map* ret = _upb_Map_New(&d->arena, key_size, val_size);
if (!ret) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); if (!ret) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
return ret; return ret;
@ -606,15 +606,16 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr,
if (entry->fields[1].descriptortype == kUpb_FieldType_Message || if (entry->fields[1].descriptortype == kUpb_FieldType_Message ||
entry->fields[1].descriptortype == kUpb_FieldType_Group) { entry->fields[1].descriptortype == kUpb_FieldType_Group) {
/* Create proactively to handle the case where it doesn't appear. */ /* Create proactively to handle the case where it doesn't appear. */
ent.v.val = ent.data.v.val =
upb_value_ptr(_upb_Message_New(entry->subs[0].submsg, &d->arena)); upb_value_ptr(_upb_Message_New(entry->subs[0].submsg, &d->arena));
} }
const char* start = ptr; const char* start = ptr;
ptr = _upb_Decoder_DecodeSubMessage(d, ptr, &ent.k, subs, field, val->size); ptr =
_upb_Decoder_DecodeSubMessage(d, ptr, &ent.data, subs, field, val->size);
// check if ent had any unknown fields // check if ent had any unknown fields
size_t size; size_t size;
upb_Message_GetUnknown(&ent.k, &size); upb_Message_GetUnknown(&ent.data, &size);
if (size != 0) { if (size != 0) {
uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Delimited; uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Delimited;
_upb_Decoder_AddUnknownVarints(d, msg, tag, (uint32_t)(ptr - start)); _upb_Decoder_AddUnknownVarints(d, msg, tag, (uint32_t)(ptr - start));
@ -622,7 +623,8 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr,
_upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
} }
} else { } else {
if (_upb_Map_Insert(map, &ent.k, map->key_size, &ent.v, map->val_size, if (_upb_Map_Insert(map, &ent.data.k, map->key_size, &ent.data.v,
map->val_size,
&d->arena) == kUpb_MapInsertStatus_OutOfMemory) { &d->arena) == kUpb_MapInsertStatus_OutOfMemory) {
_upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
} }

@ -403,8 +403,8 @@ static void encode_mapentry(upb_encstate* e, uint32_t number,
const upb_MiniTableField* val_field = &layout->fields[1]; const upb_MiniTableField* val_field = &layout->fields[1];
size_t pre_len = e->limit - e->ptr; size_t pre_len = e->limit - e->ptr;
size_t size; size_t size;
encode_scalar(e, &ent->v, layout->subs, val_field); encode_scalar(e, &ent->data.v, layout->subs, val_field);
encode_scalar(e, &ent->k, layout->subs, key_field); encode_scalar(e, &ent->data.k, layout->subs, key_field);
size = (e->limit - e->ptr) - pre_len; size = (e->limit - e->ptr) - pre_len;
encode_varint(e, size); encode_varint(e, size);
encode_tag(e, number, kUpb_WireType_Delimited); encode_tag(e, number, kUpb_WireType_Delimited);
@ -434,8 +434,8 @@ static void encode_map(upb_encstate* e, const upb_Message* msg,
upb_value val; upb_value val;
while (upb_strtable_next2(&map->table, &key, &val, &iter)) { while (upb_strtable_next2(&map->table, &key, &val, &iter)) {
upb_MapEntry ent; upb_MapEntry ent;
_upb_map_fromkey(key, &ent.k, map->key_size); _upb_map_fromkey(key, &ent.data.k, map->key_size);
_upb_map_fromvalue(val, &ent.v, map->val_size); _upb_map_fromvalue(val, &ent.data.v, map->val_size);
encode_mapentry(e, f->number, layout, &ent); encode_mapentry(e, f->number, layout, &ent);
} }
} }

@ -299,14 +299,10 @@ upb_MiniTable* FilePlatformLayout::MakeMapMiniTable(
const protobuf::Descriptor* m) { const protobuf::Descriptor* m) {
const auto key_type = static_cast<upb_FieldType>(m->map_key()->type()); const auto key_type = static_cast<upb_FieldType>(m->map_key()->type());
const auto val_type = static_cast<upb_FieldType>(m->map_value()->type()); const auto val_type = static_cast<upb_FieldType>(m->map_value()->type());
const uint64_t val_mod = (m->map_value()->enum_type() &&
m->map_value()->enum_type()->file()->syntax() ==
protobuf::FileDescriptor::SYNTAX_PROTO2)
? kUpb_FieldModifier_IsClosedEnum
: 0;
upb::MtDataEncoder e; upb::MtDataEncoder e;
e.EncodeMap(key_type, val_type, val_mod); e.EncodeMap(key_type, val_type, GetFieldModifiers(m->map_key()),
GetFieldModifiers(m->map_value()));
const absl::string_view str = e.data(); const absl::string_view str = e.data();
upb::Status status; upb::Status status;

@ -227,6 +227,9 @@ std::string CTypeConst(const protobuf::FieldDescriptor* field) {
return CTypeInternal(field, true); return CTypeInternal(field, true);
} }
std::string FieldInitializer(const FileLayout& layout,
const protobuf::FieldDescriptor* field);
void DumpEnumValues(const protobuf::EnumDescriptor* desc, Output& output) { void DumpEnumValues(const protobuf::EnumDescriptor* desc, Output& output) {
std::vector<const protobuf::EnumValueDescriptor*> values; std::vector<const protobuf::EnumValueDescriptor*> values;
for (int i = 0; i < desc->value_count(); i++) { for (int i = 0; i < desc->value_count(); i++) {
@ -256,7 +259,7 @@ void GenerateExtensionInHeader(const protobuf::FieldDescriptor* ext,
output( output(
R"cc( R"cc(
UPB_INLINE bool $0_has_$1(const struct $2* msg) { UPB_INLINE bool $0_has_$1(const struct $2* msg) {
return _upb_Message_Getext(msg, &$3) != NULL; return _upb_MiniTable_HasExtensionField(msg, &$3);
} }
)cc", )cc",
ExtensionIdentBase(ext), ext->name(), MessageName(ext->containing_type()), ExtensionIdentBase(ext), ext->name(), MessageName(ext->containing_type()),
@ -375,32 +378,35 @@ void GenerateHazzer(const protobuf::FieldDescriptor* field,
const NameToFieldDescriptorMap& field_names, const NameToFieldDescriptorMap& field_names,
Output& output) { Output& output) {
std::string resolved_name = ResolveFieldName(field, field_names); std::string resolved_name = ResolveFieldName(field, field_names);
if (layout.HasHasbit(field)) { if (field->has_presence()) {
output( output(
R"cc( R"cc(
UPB_INLINE bool $0_has_$1(const $0* msg) { UPB_INLINE bool $0_has_$1(const $0* msg) {
return _upb_hasbit(msg, $2); const upb_MiniTableField field = $2;
return _upb_MiniTable_HasNonExtensionField(msg, &field);
} }
)cc", )cc",
msg_name, resolved_name, layout.GetHasbitIndex(field)); msg_name, resolved_name, FieldInitializer(layout, field));
} else if (field->real_containing_oneof()) { } else if (field->is_map()) {
// TODO(b/259616267): remove.
output( output(
R"cc( R"cc(
UPB_INLINE bool $0_has_$1(const $0* msg) { UPB_INLINE bool $0_has_$1(const $0* msg) {
return _upb_getoneofcase(msg, $2) == $3; return $0_$1_size(msg) != 0;
} }
)cc", )cc",
msg_name, resolved_name, msg_name, resolved_name);
layout.GetOneofCaseOffset(field->real_containing_oneof()), } else if (field->is_repeated()) {
field->number()); // TODO(b/259616267): remove.
} else if (field->message_type()) {
output( output(
R"cc( R"cc(
UPB_INLINE bool $0_has_$1(const $0* msg) { UPB_INLINE bool $0_has_$1(const $0* msg) {
return _upb_has_submsg_nohasbit(msg, $2); size_t size;
$0_$1(msg, &size);
return size != 0;
} }
)cc", )cc",
msg_name, resolved_name, layout.GetFieldOffset(field)); msg_name, resolved_name);
} }
} }
@ -592,9 +598,6 @@ void GenerateRepeatedGetters(const protobuf::FieldDescriptor* field,
layout.GetFieldOffset(field)); layout.GetFieldOffset(field));
} }
std::string FieldInitializer(const FileLayout& layout,
const protobuf::FieldDescriptor* field);
void GenerateScalarGetters(const protobuf::FieldDescriptor* field, void GenerateScalarGetters(const protobuf::FieldDescriptor* field,
const FileLayout& layout, absl::string_view msg_name, const FileLayout& layout, absl::string_view msg_name,
const NameToFieldDescriptorMap& field_names, const NameToFieldDescriptorMap& field_names,
@ -798,13 +801,13 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message,
auto field_names = CreateFieldNameMap(message); auto field_names = CreateFieldNameMap(message);
for (auto field : FieldNumberOrder(message)) { for (auto field : FieldNumberOrder(message)) {
GenerateHazzer(field, layout, msg_name, field_names, output);
if (field->is_repeated()) { if (field->is_repeated()) {
GenerateRepeatedClear(field, layout, msg_name, field_names, output); GenerateRepeatedClear(field, layout, msg_name, field_names, output);
} else { } else {
GenerateClear(field, layout, msg_name, field_names, output); GenerateClear(field, layout, msg_name, field_names, output);
} }
GenerateGetters(field, layout, msg_name, field_names, output); GenerateGetters(field, layout, msg_name, field_names, output);
GenerateHazzer(field, layout, msg_name, field_names, output);
} }
output("\n"); output("\n");

Loading…
Cancel
Save