mini descriptor encode functions now populate a string view

Also fixed a few bugs in which output pointer updates were not stored.

PiperOrigin-RevId: 474884814
pull/13171/head
Eric Salo 3 years ago committed by Copybara-Service
parent 68c0a7a8e1
commit 668cebbad9
  1. 17
      upb/reflection/enum_def.c
  2. 5
      upb/reflection/enum_def.h
  3. 98
      upb/reflection/mini_descriptor_encode.c
  4. 32
      upb/reflection/mini_descriptor_encode.h
  5. 19
      upbc/code_generator_request.c

@ -91,19 +91,20 @@ static int cmp_values(const void* a, const void* b) {
return (A < B) ? -1 : (A > B); return (A < B) ? -1 : (A > B);
} }
const char* _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a) { bool _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a,
if (e->is_sorted) return _upb_MiniDescriptor_EncodeEnum(e, NULL, a); upb_StringView* out) {
if (e->is_sorted) return _upb_MiniDescriptor_EncodeEnum(e, NULL, a, out);
const upb_EnumValueDef** sorted = (const upb_EnumValueDef**)upb_Arena_Malloc( const upb_EnumValueDef** sorted = (const upb_EnumValueDef**)upb_Arena_Malloc(
a, e->value_count * sizeof(void*)); a, e->value_count * sizeof(void*));
if (!sorted) return NULL; if (!sorted) return false;
for (size_t i = 0; i < e->value_count; i++) { for (size_t i = 0; i < e->value_count; i++) {
sorted[i] = upb_EnumDef_Value(e, i); sorted[i] = upb_EnumDef_Value(e, i);
} }
qsort(sorted, e->value_count, sizeof(void*), cmp_values); qsort(sorted, e->value_count, sizeof(void*), cmp_values);
return _upb_MiniDescriptor_EncodeEnum(e, sorted, a); return _upb_MiniDescriptor_EncodeEnum(e, sorted, a, out);
} }
const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) { const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) {
@ -166,13 +167,13 @@ const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) {
static upb_MiniTable_Enum* create_enumlayout(upb_DefBuilder* ctx, static upb_MiniTable_Enum* create_enumlayout(upb_DefBuilder* ctx,
const upb_EnumDef* e) { const upb_EnumDef* e) {
const char* desc = _upb_EnumDef_MiniDescriptor(e, ctx->tmp_arena); upb_StringView sv;
if (!desc) bool ok = _upb_EnumDef_MiniDescriptor(e, ctx->tmp_arena, &sv);
_upb_DefBuilder_Errf(ctx, "OOM while building enum MiniDescriptor"); if (!ok) _upb_DefBuilder_Errf(ctx, "OOM while building enum MiniDescriptor");
upb_Status status; upb_Status status;
upb_MiniTable_Enum* layout = upb_MiniTable_Enum* layout =
upb_MiniTable_BuildEnum(desc, strlen(desc), ctx->arena, &status); upb_MiniTable_BuildEnum(sv.data, sv.size, ctx->arena, &status);
if (!layout) if (!layout)
_upb_DefBuilder_Errf(ctx, "Error building enum MiniTable: %s", status.msg); _upb_DefBuilder_Errf(ctx, "Error building enum MiniTable: %s", status.msg);
return layout; return layout;

@ -62,8 +62,9 @@ upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i);
bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a); bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a);
const upb_MiniTable_Enum* _upb_EnumDef_MiniTable(const upb_EnumDef* e); const upb_MiniTable_Enum* _upb_EnumDef_MiniTable(const upb_EnumDef* e);
// Builds and returns a mini descriptor, or NULL if OOM. // Builds a mini descriptor, returns false if OOM.
const char* _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a); bool _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a,
upb_StringView* out);
// Allocate and initialize an array of |n| enum defs. // Allocate and initialize an array of |n| enum defs.
upb_EnumDef* _upb_EnumDefs_New(upb_DefBuilder* ctx, int n, upb_EnumDef* _upb_EnumDefs_New(upb_DefBuilder* ctx, int n,

@ -130,65 +130,68 @@ static int upb_MiniDescriptor_CompareFields(const void* a, const void* b) {
return 0; return 0;
} }
const char* _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, bool _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
const upb_EnumValueDef** sorted, const upb_EnumValueDef** sorted,
upb_Arena* a) { upb_Arena* a, upb_StringView* out) {
DescState s; DescState s;
upb_DescState_Init(&s); upb_DescState_Init(&s);
upb_MtDataEncoder_StartEnum(&s.e); upb_MtDataEncoder_StartEnum(&s.e);
const size_t value_count = upb_EnumDef_ValueCount(e);
// Duplicate values are allowed but we only encode each value once. // Duplicate values are allowed but we only encode each value once.
uint32_t previous = 0; uint32_t previous = 0;
const size_t value_count = upb_EnumDef_ValueCount(e);
for (size_t i = 0; i < value_count; i++) { for (size_t i = 0; i < value_count; i++) {
const uint32_t current = const uint32_t current =
upb_EnumValueDef_Number(sorted ? sorted[i] : upb_EnumDef_Value(e, i)); upb_EnumValueDef_Number(sorted ? sorted[i] : upb_EnumDef_Value(e, i));
if (i != 0 && previous == current) continue; if (i != 0 && previous == current) continue;
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, current); s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, current);
previous = current; previous = current;
} }
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_EndEnum(&s.e, s.ptr); s.ptr = upb_MtDataEncoder_EndEnum(&s.e, s.ptr);
// There will always be room for this '\0' in the encoder buffer because // There will always be room for this '\0' in the encoder buffer because
// kUpb_MtDataEncoder_MinSize is overkill for upb_MtDataEncoder_EndEnum(). // kUpb_MtDataEncoder_MinSize is overkill for upb_MtDataEncoder_EndEnum().
UPB_ASSERT(s.ptr < s.buf + s.bufsize); UPB_ASSERT(s.ptr < s.buf + s.bufsize);
*s.ptr++ = '\0'; *s.ptr = '\0';
return s.buf; out->data = s.buf;
out->size = s.ptr - s.buf;
return true;
} }
const char* _upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, bool _upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a,
upb_Arena* a) { upb_StringView* out) {
UPB_ASSERT(upb_FieldDef_IsExtension(f)); UPB_ASSERT(upb_FieldDef_IsExtension(f));
DescState s; DescState s;
upb_DescState_Init(&s); upb_DescState_Init(&s);
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0); s.ptr = upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0);
const upb_FieldType type = upb_FieldDef_Type(f); const upb_FieldType type = upb_FieldDef_Type(f);
const int number = upb_FieldDef_Number(f); const int number = upb_FieldDef_Number(f);
const uint64_t modifiers = upb_Field_Modifiers(f); const uint64_t modifiers = upb_Field_Modifiers(f);
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers); s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers);
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
*s.ptr++ = '\0'; *s.ptr = '\0';
return s.buf; out->data = s.buf;
out->size = s.ptr - s.buf;
return true;
} }
const char* _upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, bool _upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a,
upb_Arena* a) { upb_StringView* out) {
DescState s; DescState s;
upb_DescState_Init(&s); upb_DescState_Init(&s);
@ -196,7 +199,7 @@ const char* _upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m,
const size_t field_count = upb_MessageDef_FieldCount(m); const size_t field_count = upb_MessageDef_FieldCount(m);
const upb_FieldDef** sorted = const upb_FieldDef** sorted =
(const upb_FieldDef**)upb_Arena_Malloc(a, field_count * sizeof(void*)); (const upb_FieldDef**)upb_Arena_Malloc(a, field_count * sizeof(void*));
if (!sorted) return NULL; if (!sorted) return false;
// Sort the copy. // Sort the copy.
for (size_t i = 0; i < field_count; i++) { for (size_t i = 0; i < field_count; i++) {
@ -204,56 +207,55 @@ const char* _upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m,
} }
qsort(sorted, field_count, sizeof(void*), upb_MiniDescriptor_CompareFields); qsort(sorted, field_count, sizeof(void*), upb_MiniDescriptor_CompareFields);
// Start encoding. if (!upb_DescState_Grow(&s, a)) return false;
if (!upb_DescState_Grow(&s, a)) return NULL; s.ptr = upb_MtDataEncoder_StartMessage(&s.e, s.ptr, upb_Message_Modifiers(m));
upb_MtDataEncoder_StartMessage(&s.e, s.ptr, upb_Message_Modifiers(m));
// Encode the fields.
for (size_t i = 0; i < field_count; i++) { for (size_t i = 0; i < field_count; i++) {
const upb_FieldDef* field_def = sorted[i]; const upb_FieldDef* f = sorted[i];
const upb_FieldType type = upb_FieldDef_Type(field_def); const upb_FieldType type = upb_FieldDef_Type(f);
const int number = upb_FieldDef_Number(field_def); const int number = upb_FieldDef_Number(f);
const uint64_t modifiers = upb_Field_Modifiers(field_def); const uint64_t modifiers = upb_Field_Modifiers(f);
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers); s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers);
} }
// Encode the oneofs.
const int oneof_count = upb_MessageDef_OneofCount(m); const int oneof_count = upb_MessageDef_OneofCount(m);
for (int i = 0; i < oneof_count; i++) { for (int i = 0; i < oneof_count; i++) {
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_StartOneof(&s.e, s.ptr); s.ptr = upb_MtDataEncoder_StartOneof(&s.e, s.ptr);
const upb_OneofDef* oneof_def = upb_MessageDef_Oneof(m, i); const upb_OneofDef* o = upb_MessageDef_Oneof(m, i);
const int field_count = upb_OneofDef_FieldCount(oneof_def); const int field_count = upb_OneofDef_FieldCount(o);
for (int j = 0; j < field_count; j++) { for (int j = 0; j < field_count; j++) {
const upb_FieldDef* field_def = upb_OneofDef_Field(oneof_def, j); const int number = upb_FieldDef_Number(upb_OneofDef_Field(o, j));
const int number = upb_FieldDef_Number(field_def);
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_PutOneofField(&s.e, s.ptr, number); s.ptr = upb_MtDataEncoder_PutOneofField(&s.e, s.ptr, number);
} }
} }
if (!upb_DescState_Grow(&s, a)) return NULL; if (!upb_DescState_Grow(&s, a)) return false;
*s.ptr++ = '\0'; *s.ptr = '\0';
return s.buf; out->data = s.buf;
out->size = s.ptr - s.buf;
return true;
} }
/******************************************************************************/ /******************************************************************************/
const char* upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a) { bool upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a,
return _upb_EnumDef_MiniDescriptor(e, a); upb_StringView* out) {
return _upb_EnumDef_MiniDescriptor(e, a, out);
} }
const char* upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, bool upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a,
upb_Arena* a) { upb_StringView* out) {
return _upb_MiniDescriptor_EncodeField(f, a); return _upb_MiniDescriptor_EncodeField(f, a, out);
} }
const char* upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a,
upb_Arena* a) { upb_StringView* out) {
return _upb_MiniDescriptor_EncodeMessage(m, a); return _upb_MiniDescriptor_EncodeMessage(m, a, out);
} }

@ -29,6 +29,7 @@
#define UPB_REFLECTION_MINI_DESCRIPTOR_ENCODE_H_ #define UPB_REFLECTION_MINI_DESCRIPTOR_ENCODE_H_
#include "upb/reflection/common.h" #include "upb/reflection/common.h"
#include "upb/string_view.h"
// Must be last. // Must be last.
#include "upb/port_def.inc" #include "upb/port_def.inc"
@ -37,15 +38,17 @@
extern "C" { extern "C" {
#endif #endif
// Creates and returns a mini descriptor string for an enum, or NULL on error. // Creates a mini descriptor string for an enum, returns true on success.
const char* upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a); bool upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a,
upb_StringView* out);
// Creates and returns a mini descriptor string for a field, or NULL on error. // Creates a mini descriptor string for a field, returns true on success.
const char* upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a); bool upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a,
upb_StringView* out);
// Creates and returns a mini descriptor string for a message, or NULL on error. // Creates a mini descriptor string for a message, returns true on success.
const char* upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a,
upb_Arena* a); upb_StringView* out);
// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// // EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
@ -53,17 +56,12 @@ const char* upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m,
// If the values in the enum happen to be defined in ascending order (when cast // If the values in the enum happen to be defined in ascending order (when cast
// to uint32_t) then |sorted| should be NULL. Otherwise it must point to an // to uint32_t) then |sorted| should be NULL. Otherwise it must point to an
// array containing pointers to the enum value defs in sorted order. // array containing pointers to the enum value defs in sorted order.
const char* _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, bool _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
const upb_EnumValueDef** sorted, const upb_EnumValueDef** sorted,
upb_Arena* a); upb_Arena* a, upb_StringView* out);
// Creates and returns a mini descriptor string for a field, or NULL on error.
const char* _upb_MiniDescriptor_EncodeField(const upb_FieldDef* f,
upb_Arena* a);
// Creates and returns a mini descriptor string for a message, or NULL on error. bool _upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a,
const char* _upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_StringView* out);
upb_Arena* a);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

@ -71,9 +71,9 @@ static void upbc_State_Init(upbc_State* s) {
if (!s->out) upbc_Error(s, __func__, "could not allocate request"); if (!s->out) upbc_Error(s, __func__, "could not allocate request");
} }
static void upbc_State_Emit(upbc_State* s, const char* name, const char* data) { static void upbc_State_Emit(upbc_State* s, const char* name,
upb_StringView encoding) {
const upb_StringView key = upb_StringView_FromString(name); const upb_StringView key = upb_StringView_FromString(name);
const upb_StringView encoding = upb_StringView_FromString(data);
bool ok = upbc_CodeGeneratorRequest_mini_descriptors_set(s->out, key, bool ok = upbc_CodeGeneratorRequest_mini_descriptors_set(s->out, key,
encoding, s->arena); encoding, s->arena);
if (!ok) upbc_Error(s, __func__, "could not set mini descriptor in map"); if (!ok) upbc_Error(s, __func__, "could not set mini descriptor in map");
@ -85,15 +85,17 @@ static void upbc_State_Emit(upbc_State* s, const char* name, const char* data) {
static void upbc_Scrape_Message(upbc_State*, const upb_MessageDef*); static void upbc_Scrape_Message(upbc_State*, const upb_MessageDef*);
static void upbc_Scrape_Enum(upbc_State* s, const upb_EnumDef* e) { static void upbc_Scrape_Enum(upbc_State* s, const upb_EnumDef* e) {
const char* desc = upb_MiniDescriptor_EncodeEnum(e, s->arena); upb_StringView desc;
if (!desc) upbc_Error(s, __func__, "could not encode enum"); bool ok = upb_MiniDescriptor_EncodeEnum(e, s->arena, &desc);
if (!ok) upbc_Error(s, __func__, "could not encode enum");
upbc_State_Emit(s, upb_EnumDef_FullName(e), desc); upbc_State_Emit(s, upb_EnumDef_FullName(e), desc);
} }
static void upbc_Scrape_Extension(upbc_State* s, const upb_FieldDef* f) { static void upbc_Scrape_Extension(upbc_State* s, const upb_FieldDef* f) {
const char* desc = upb_MiniDescriptor_EncodeField(f, s->arena); upb_StringView desc;
if (!desc) upbc_Error(s, __func__, "could not encode extension"); bool ok = upb_MiniDescriptor_EncodeField(f, s->arena, &desc);
if (!ok) upbc_Error(s, __func__, "could not encode extension");
upbc_State_Emit(s, upb_FieldDef_FullName(f), desc); upbc_State_Emit(s, upb_FieldDef_FullName(f), desc);
} }
@ -170,8 +172,9 @@ static void upbc_Scrape_NestedMessages(upbc_State* s, const upb_MessageDef* m) {
} }
static void upbc_Scrape_Message(upbc_State* s, const upb_MessageDef* m) { static void upbc_Scrape_Message(upbc_State* s, const upb_MessageDef* m) {
const char* desc = upb_MiniDescriptor_EncodeMessage(m, s->arena); upb_StringView desc;
if (!desc) upbc_Error(s, __func__, "could not encode message"); bool ok = upb_MiniDescriptor_EncodeMessage(m, s->arena, &desc);
if (!ok) upbc_Error(s, __func__, "could not encode message");
upbc_State_Emit(s, upb_MessageDef_FullName(m), desc); upbc_State_Emit(s, upb_MessageDef_FullName(m), desc);

Loading…
Cancel
Save