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);
}
const char* _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a) {
if (e->is_sorted) return _upb_MiniDescriptor_EncodeEnum(e, NULL, a);
bool _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* 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(
a, e->value_count * sizeof(void*));
if (!sorted) return NULL;
if (!sorted) return false;
for (size_t i = 0; i < e->value_count; i++) {
sorted[i] = upb_EnumDef_Value(e, i);
}
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) {
@ -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,
const upb_EnumDef* e) {
const char* desc = _upb_EnumDef_MiniDescriptor(e, ctx->tmp_arena);
if (!desc)
_upb_DefBuilder_Errf(ctx, "OOM while building enum MiniDescriptor");
upb_StringView sv;
bool ok = _upb_EnumDef_MiniDescriptor(e, ctx->tmp_arena, &sv);
if (!ok) _upb_DefBuilder_Errf(ctx, "OOM while building enum MiniDescriptor");
upb_Status status;
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)
_upb_DefBuilder_Errf(ctx, "Error building enum MiniTable: %s", status.msg);
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);
const upb_MiniTable_Enum* _upb_EnumDef_MiniTable(const upb_EnumDef* e);
// Builds and returns a mini descriptor, or NULL if OOM.
const char* _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a);
// Builds a mini descriptor, returns false if OOM.
bool _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a,
upb_StringView* out);
// Allocate and initialize an array of |n| enum defs.
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;
}
const char* _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
const upb_EnumValueDef** sorted,
upb_Arena* a) {
bool _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
const upb_EnumValueDef** sorted,
upb_Arena* a, upb_StringView* out) {
DescState s;
upb_DescState_Init(&s);
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.
uint32_t previous = 0;
const size_t value_count = upb_EnumDef_ValueCount(e);
for (size_t i = 0; i < value_count; i++) {
const uint32_t current =
upb_EnumValueDef_Number(sorted ? sorted[i] : upb_EnumDef_Value(e, i));
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);
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);
// There will always be room for this '\0' in the encoder buffer because
// kUpb_MtDataEncoder_MinSize is overkill for upb_MtDataEncoder_EndEnum().
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,
upb_Arena* a) {
bool _upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a,
upb_StringView* out) {
UPB_ASSERT(upb_FieldDef_IsExtension(f));
DescState s;
upb_DescState_Init(&s);
if (!upb_DescState_Grow(&s, a)) return NULL;
upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0);
if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0);
const upb_FieldType type = upb_FieldDef_Type(f);
const int number = upb_FieldDef_Number(f);
const uint64_t modifiers = upb_Field_Modifiers(f);
if (!upb_DescState_Grow(&s, a)) return NULL;
upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers);
if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers);
if (!upb_DescState_Grow(&s, a)) return NULL;
*s.ptr++ = '\0';
if (!upb_DescState_Grow(&s, a)) return false;
*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,
upb_Arena* a) {
bool _upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a,
upb_StringView* out) {
DescState 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 upb_FieldDef** sorted =
(const upb_FieldDef**)upb_Arena_Malloc(a, field_count * sizeof(void*));
if (!sorted) return NULL;
if (!sorted) return false;
// Sort the copy.
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);
// Start encoding.
if (!upb_DescState_Grow(&s, a)) return NULL;
upb_MtDataEncoder_StartMessage(&s.e, s.ptr, upb_Message_Modifiers(m));
if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_StartMessage(&s.e, s.ptr, upb_Message_Modifiers(m));
// Encode the fields.
for (size_t i = 0; i < field_count; i++) {
const upb_FieldDef* field_def = sorted[i];
const upb_FieldType type = upb_FieldDef_Type(field_def);
const int number = upb_FieldDef_Number(field_def);
const uint64_t modifiers = upb_Field_Modifiers(field_def);
const upb_FieldDef* f = sorted[i];
const upb_FieldType type = upb_FieldDef_Type(f);
const int number = upb_FieldDef_Number(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;
s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers);
}
// Encode the oneofs.
const int oneof_count = upb_MessageDef_OneofCount(m);
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);
const upb_OneofDef* oneof_def = upb_MessageDef_Oneof(m, i);
const int field_count = upb_OneofDef_FieldCount(oneof_def);
const upb_OneofDef* o = upb_MessageDef_Oneof(m, i);
const int field_count = upb_OneofDef_FieldCount(o);
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(field_def);
const int number = upb_FieldDef_Number(upb_OneofDef_Field(o, j));
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);
}
}
if (!upb_DescState_Grow(&s, a)) return NULL;
*s.ptr++ = '\0';
if (!upb_DescState_Grow(&s, a)) return false;
*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) {
return _upb_EnumDef_MiniDescriptor(e, a);
bool upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a,
upb_StringView* out) {
return _upb_EnumDef_MiniDescriptor(e, a, out);
}
const char* upb_MiniDescriptor_EncodeField(const upb_FieldDef* f,
upb_Arena* a) {
return _upb_MiniDescriptor_EncodeField(f, a);
bool upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a,
upb_StringView* out) {
return _upb_MiniDescriptor_EncodeField(f, a, out);
}
const char* upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m,
upb_Arena* a) {
return _upb_MiniDescriptor_EncodeMessage(m, a);
bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a,
upb_StringView* out) {
return _upb_MiniDescriptor_EncodeMessage(m, a, out);
}

@ -29,6 +29,7 @@
#define UPB_REFLECTION_MINI_DESCRIPTOR_ENCODE_H_
#include "upb/reflection/common.h"
#include "upb/string_view.h"
// Must be last.
#include "upb/port_def.inc"
@ -37,15 +38,17 @@
extern "C" {
#endif
// Creates and returns a mini descriptor string for an enum, or NULL on error.
const char* upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a);
// Creates a mini descriptor string for an enum, returns true on success.
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.
const char* upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a);
// Creates a mini descriptor string for a field, returns true on success.
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.
const char* upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m,
upb_Arena* a);
// Creates a mini descriptor string for a message, returns true on success.
bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a,
upb_StringView* out);
// 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
// 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.
const char* _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
const upb_EnumValueDef** sorted,
upb_Arena* a);
// 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);
bool _upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
const upb_EnumValueDef** sorted,
upb_Arena* a, upb_StringView* out);
// Creates and returns a mini descriptor string for a message, or NULL on error.
const char* _upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m,
upb_Arena* a);
bool _upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a,
upb_StringView* out);
#ifdef __cplusplus
} /* 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");
}
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 encoding = upb_StringView_FromString(data);
bool ok = upbc_CodeGeneratorRequest_mini_descriptors_set(s->out, key,
encoding, s->arena);
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_Enum(upbc_State* s, const upb_EnumDef* e) {
const char* desc = upb_MiniDescriptor_EncodeEnum(e, s->arena);
if (!desc) upbc_Error(s, __func__, "could not encode enum");
upb_StringView desc;
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);
}
static void upbc_Scrape_Extension(upbc_State* s, const upb_FieldDef* f) {
const char* desc = upb_MiniDescriptor_EncodeField(f, s->arena);
if (!desc) upbc_Error(s, __func__, "could not encode extension");
upb_StringView desc;
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);
}
@ -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) {
const char* desc = upb_MiniDescriptor_EncodeMessage(m, s->arena);
if (!desc) upbc_Error(s, __func__, "could not encode message");
upb_StringView desc;
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);

Loading…
Cancel
Save