diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index fb226ca3c7a0..e02c084a12bb 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -3100,12 +3100,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, @@ -3836,19 +3841,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)); @@ -3858,15 +3863,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}; } } @@ -3909,8 +3915,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); } @@ -3923,11 +3931,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); } @@ -4008,8 +4019,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; @@ -4024,7 +4037,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); @@ -4040,15 +4053,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, @@ -4473,8 +4494,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, diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c index eac3e83cee60..d2ea1895bc53 100644 --- a/ruby/ext/google/protobuf_c/ruby-upb.c +++ b/ruby/ext/google/protobuf_c/ruby-upb.c @@ -2616,12 +2616,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, @@ -3352,19 +3357,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)); @@ -3374,15 +3379,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}; } } @@ -3425,8 +3431,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); } @@ -3439,11 +3447,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); } @@ -3524,8 +3535,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; @@ -3540,7 +3553,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); @@ -3556,15 +3569,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, @@ -3989,8 +4010,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,