|
|
|
@ -51,12 +51,17 @@ typedef struct {
|
|
|
|
|
const upb_FieldDef* debug_field;
|
|
|
|
|
} jsondec;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
upb_MessageValue value;
|
|
|
|
|
bool ignore;
|
|
|
|
|
} upb_JsonMessageValue;
|
|
|
|
|
|
|
|
|
|
enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL };
|
|
|
|
|
|
|
|
|
|
/* Forward declarations of mutually-recursive functions. */
|
|
|
|
|
static void jsondec_wellknown(jsondec* d, upb_Message* msg,
|
|
|
|
|
const upb_MessageDef* m);
|
|
|
|
|
static upb_MessageValue jsondec_value(jsondec* d, const upb_FieldDef* f);
|
|
|
|
|
static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f);
|
|
|
|
|
static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg,
|
|
|
|
|
const upb_MessageDef* m);
|
|
|
|
|
static void jsondec_object(jsondec* d, upb_Message* msg,
|
|
|
|
@ -787,19 +792,19 @@ static upb_MessageValue jsondec_strfield(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static upb_MessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
switch (jsondec_peek(d)) {
|
|
|
|
|
case JD_STRING: {
|
|
|
|
|
upb_StringView str = jsondec_string(d);
|
|
|
|
|
const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f);
|
|
|
|
|
const upb_EnumValueDef* ev =
|
|
|
|
|
upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size);
|
|
|
|
|
upb_MessageValue val;
|
|
|
|
|
upb_JsonMessageValue val = {.ignore = false};
|
|
|
|
|
if (ev) {
|
|
|
|
|
val.int32_val = upb_EnumValueDef_Number(ev);
|
|
|
|
|
val.value.int32_val = upb_EnumValueDef_Number(ev);
|
|
|
|
|
} else {
|
|
|
|
|
if (d->options & upb_JsonDecode_IgnoreUnknown) {
|
|
|
|
|
val.int32_val = 0;
|
|
|
|
|
val.ignore = true;
|
|
|
|
|
} else {
|
|
|
|
|
jsondec_errf(d, "Unknown enumerator: '" UPB_STRINGVIEW_FORMAT "'",
|
|
|
|
|
UPB_STRINGVIEW_ARGS(str));
|
|
|
|
@ -809,15 +814,16 @@ static upb_MessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
}
|
|
|
|
|
case JD_NULL: {
|
|
|
|
|
if (jsondec_isnullvalue(f)) {
|
|
|
|
|
upb_MessageValue val;
|
|
|
|
|
upb_JsonMessageValue val = {.ignore = false};
|
|
|
|
|
jsondec_null(d);
|
|
|
|
|
val.int32_val = 0;
|
|
|
|
|
val.value.int32_val = 0;
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Fallthrough. */
|
|
|
|
|
default:
|
|
|
|
|
return jsondec_int(d, f);
|
|
|
|
|
return (upb_JsonMessageValue){.value = jsondec_int(d, f),
|
|
|
|
|
.ignore = false};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -860,8 +866,10 @@ static void jsondec_array(jsondec* d, upb_Message* msg, const upb_FieldDef* f) {
|
|
|
|
|
|
|
|
|
|
jsondec_arrstart(d);
|
|
|
|
|
while (jsondec_arrnext(d)) {
|
|
|
|
|
upb_MessageValue elem = jsondec_value(d, f);
|
|
|
|
|
upb_Array_Append(arr, elem, d->arena);
|
|
|
|
|
upb_JsonMessageValue elem = jsondec_value(d, f);
|
|
|
|
|
if (!elem.ignore) {
|
|
|
|
|
upb_Array_Append(arr, elem.value, d->arena);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
jsondec_arrend(d);
|
|
|
|
|
}
|
|
|
|
@ -874,11 +882,14 @@ static void jsondec_map(jsondec* d, upb_Message* msg, const upb_FieldDef* f) {
|
|
|
|
|
|
|
|
|
|
jsondec_objstart(d);
|
|
|
|
|
while (jsondec_objnext(d)) {
|
|
|
|
|
upb_MessageValue key, val;
|
|
|
|
|
upb_JsonMessageValue key, val;
|
|
|
|
|
key = jsondec_value(d, key_f);
|
|
|
|
|
UPB_ASSUME(!key.ignore); // Map key cannot be enum.
|
|
|
|
|
jsondec_entrysep(d);
|
|
|
|
|
val = jsondec_value(d, val_f);
|
|
|
|
|
upb_Map_Set(map, key, val, d->arena);
|
|
|
|
|
if (!val.ignore) {
|
|
|
|
|
upb_Map_Set(map, key.value, val.value, d->arena);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
jsondec_objend(d);
|
|
|
|
|
}
|
|
|
|
@ -959,8 +970,10 @@ static void jsondec_field(jsondec* d, upb_Message* msg,
|
|
|
|
|
const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
|
|
|
|
|
jsondec_tomsg(d, submsg, subm);
|
|
|
|
|
} else {
|
|
|
|
|
upb_MessageValue val = jsondec_value(d, f);
|
|
|
|
|
upb_Message_SetFieldByDef(msg, f, val, d->arena);
|
|
|
|
|
upb_JsonMessageValue val = jsondec_value(d, f);
|
|
|
|
|
if (!val.ignore) {
|
|
|
|
|
upb_Message_SetFieldByDef(msg, f, val.value, d->arena);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d->debug_field = preserved;
|
|
|
|
@ -975,7 +988,7 @@ static void jsondec_object(jsondec* d, upb_Message* msg,
|
|
|
|
|
jsondec_objend(d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static upb_MessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
static upb_MessageValue jsondec_nonenum(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
switch (upb_FieldDef_CType(f)) {
|
|
|
|
|
case kUpb_CType_Bool:
|
|
|
|
|
return jsondec_bool(d, f);
|
|
|
|
@ -991,15 +1004,23 @@ static upb_MessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
case kUpb_CType_String:
|
|
|
|
|
case kUpb_CType_Bytes:
|
|
|
|
|
return jsondec_strfield(d, f);
|
|
|
|
|
case kUpb_CType_Enum:
|
|
|
|
|
return jsondec_enum(d, f);
|
|
|
|
|
case kUpb_CType_Message:
|
|
|
|
|
return jsondec_msg(d, f);
|
|
|
|
|
case kUpb_CType_Enum:
|
|
|
|
|
default:
|
|
|
|
|
UPB_UNREACHABLE();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) {
|
|
|
|
|
if (upb_FieldDef_CType(f) == kUpb_CType_Enum) {
|
|
|
|
|
return jsondec_enum(d, f);
|
|
|
|
|
} else {
|
|
|
|
|
return (upb_JsonMessageValue){.value = jsondec_nonenum(d, f),
|
|
|
|
|
.ignore = false};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Well-known types ***********************************************************/
|
|
|
|
|
|
|
|
|
|
static int jsondec_tsdigits(jsondec* d, const char** ptr, size_t digits,
|
|
|
|
@ -1424,8 +1445,9 @@ static void jsondec_any(jsondec* d, upb_Message* msg, const upb_MessageDef* m) {
|
|
|
|
|
static void jsondec_wrapper(jsondec* d, upb_Message* msg,
|
|
|
|
|
const upb_MessageDef* m) {
|
|
|
|
|
const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
|
|
|
|
upb_MessageValue val = jsondec_value(d, value_f);
|
|
|
|
|
upb_Message_SetFieldByDef(msg, value_f, val, d->arena);
|
|
|
|
|
upb_JsonMessageValue val = jsondec_value(d, value_f);
|
|
|
|
|
UPB_ASSUME(val.ignore == false); // Wrapper cannot be an enum.
|
|
|
|
|
upb_Message_SetFieldByDef(msg, value_f, val.value, d->arena);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void jsondec_wellknown(jsondec* d, upb_Message* msg,
|
|
|
|
|