diff --git a/upb/message/value.h b/upb/message/value.h index bb1dbbdcbd5c7..04a6a55c78dd3 100644 --- a/upb/message/value.h +++ b/upb/message/value.h @@ -15,6 +15,7 @@ #include #include "upb/base/string_view.h" +#include "upb/message/internal/types.h" // Must be last. #include "upb/port/def.inc" @@ -41,6 +42,14 @@ typedef union { // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more // information. uintptr_t tagged_msg_val; // upb_TaggedMessagePtr + + // For an extension field, we are essentially treating ext->data (a + // upb_MessageValue) as if it were a message with one field that lives at + // offset 0. This works because upb_MessageValue is precisely one value that + // can hold any type of data. Recall that an extension can be of any type + // (scalar, repeated, or message). For a message extension, that will be a + // single upb_Message* at offset 0 of the upb_MessageValue. + struct upb_Message UPB_PRIVATE(ext_msg_val); } upb_MessageValue; UPB_API_INLINE upb_MessageValue upb_MessageValue_Zero(void) { diff --git a/upb/wire/decode.c b/upb/wire/decode.c index 55e62ebea57e1..8911efdf87131 100644 --- a/upb/wire/decode.c +++ b/upb/wire/decode.c @@ -828,7 +828,7 @@ static void upb_Decoder_AddKnownMessageSetItem( } upb_Message* submsg = _upb_Decoder_NewSubMessage2( d, ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg), - &ext->ext->UPB_PRIVATE(field), (upb_TaggedMessagePtr*)&ext->data); + &ext->ext->UPB_PRIVATE(field), &ext->data.tagged_msg_val); upb_DecodeStatus status = upb_Decode( data, size, submsg, upb_MiniTableExtension_GetSubMessage(item_mt), d->extreg, d->options, &d->arena); @@ -1182,7 +1182,7 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr, _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } d->original_msg = msg; - msg = (upb_Message*)&ext->data; + msg = &ext->data.UPB_PRIVATE(ext_msg_val); if (upb_MiniTableField_IsSubMessage(&ext->ext->UPB_PRIVATE(field))) { ext_sub.UPB_PRIVATE(submsg) = &ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg); diff --git a/upb/wire/encode.c b/upb/wire/encode.c index 85764e3eb01ae..d3e68f17df717 100644 --- a/upb/wire/encode.c +++ b/upb/wire/encode.c @@ -547,7 +547,7 @@ static void encode_ext(upb_encstate* e, const upb_Extension* ext, sub.UPB_PRIVATE(subenum) = ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(subenum); } - encode_field(e, (upb_Message*)&ext->data, &sub, + encode_field(e, &ext->data.UPB_PRIVATE(ext_msg_val), &sub, &ext->ext->UPB_PRIVATE(field)); } }