File indexing completed on 2025-01-31 10:12:20
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
0009 #define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
0010
0011 #include "google/protobuf/extension_set.h"
0012 #include "google/protobuf/metadata_lite.h"
0013 #include "google/protobuf/parse_context.h"
0014
0015 namespace google {
0016 namespace protobuf {
0017 namespace internal {
0018
0019 template <typename T>
0020 const char* ExtensionSet::ParseFieldWithExtensionInfo(
0021 int number, bool was_packed_on_wire, const ExtensionInfo& extension,
0022 InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) {
0023 if (was_packed_on_wire) {
0024 switch (extension.type) {
0025 #define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE) \
0026 case WireFormatLite::TYPE_##UPPERCASE: \
0027 return internal::Packed##CPP_CAMELCASE##Parser( \
0028 MutableRawRepeatedField(number, extension.type, extension.is_packed, \
0029 extension.descriptor), \
0030 ptr, ctx);
0031 HANDLE_TYPE(INT32, Int32);
0032 HANDLE_TYPE(INT64, Int64);
0033 HANDLE_TYPE(UINT32, UInt32);
0034 HANDLE_TYPE(UINT64, UInt64);
0035 HANDLE_TYPE(SINT32, SInt32);
0036 HANDLE_TYPE(SINT64, SInt64);
0037 HANDLE_TYPE(FIXED32, Fixed32);
0038 HANDLE_TYPE(FIXED64, Fixed64);
0039 HANDLE_TYPE(SFIXED32, SFixed32);
0040 HANDLE_TYPE(SFIXED64, SFixed64);
0041 HANDLE_TYPE(FLOAT, Float);
0042 HANDLE_TYPE(DOUBLE, Double);
0043 HANDLE_TYPE(BOOL, Bool);
0044 #undef HANDLE_TYPE
0045
0046 case WireFormatLite::TYPE_ENUM:
0047 return internal::PackedEnumParserArg<T>(
0048 MutableRawRepeatedField(number, extension.type, extension.is_packed,
0049 extension.descriptor),
0050 ptr, ctx, extension.enum_validity_check.func,
0051 extension.enum_validity_check.arg, metadata, number);
0052 case WireFormatLite::TYPE_STRING:
0053 case WireFormatLite::TYPE_BYTES:
0054 case WireFormatLite::TYPE_GROUP:
0055 case WireFormatLite::TYPE_MESSAGE:
0056 ABSL_LOG(FATAL) << "Non-primitive types can't be packed.";
0057 break;
0058 }
0059 } else {
0060 switch (extension.type) {
0061 #define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE) \
0062 case WireFormatLite::TYPE_##UPPERCASE: { \
0063 uint64_t value; \
0064 ptr = VarintParse(ptr, &value); \
0065 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
0066 if (extension.is_repeated) { \
0067 Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
0068 extension.is_packed, value, extension.descriptor); \
0069 } else { \
0070 Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
0071 extension.descriptor); \
0072 } \
0073 } break
0074
0075 HANDLE_VARINT_TYPE(INT32, Int32);
0076 HANDLE_VARINT_TYPE(INT64, Int64);
0077 HANDLE_VARINT_TYPE(UINT32, UInt32);
0078 HANDLE_VARINT_TYPE(UINT64, UInt64);
0079 HANDLE_VARINT_TYPE(BOOL, Bool);
0080 #undef HANDLE_VARINT_TYPE
0081 #define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE) \
0082 case WireFormatLite::TYPE_##UPPERCASE: { \
0083 uint64_t val; \
0084 ptr = VarintParse(ptr, &val); \
0085 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \
0086 auto value = WireFormatLite::ZigZagDecode##SIZE(val); \
0087 if (extension.is_repeated) { \
0088 Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
0089 extension.is_packed, value, extension.descriptor); \
0090 } else { \
0091 Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
0092 extension.descriptor); \
0093 } \
0094 } break
0095
0096 HANDLE_SVARINT_TYPE(SINT32, Int32, 32);
0097 HANDLE_SVARINT_TYPE(SINT64, Int64, 64);
0098 #undef HANDLE_SVARINT_TYPE
0099 #define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE) \
0100 case WireFormatLite::TYPE_##UPPERCASE: { \
0101 auto value = UnalignedLoad<CPPTYPE>(ptr); \
0102 ptr += sizeof(CPPTYPE); \
0103 if (extension.is_repeated) { \
0104 Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
0105 extension.is_packed, value, extension.descriptor); \
0106 } else { \
0107 Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
0108 extension.descriptor); \
0109 } \
0110 } break
0111
0112 HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32_t);
0113 HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64_t);
0114 HANDLE_FIXED_TYPE(SFIXED32, Int32, int32_t);
0115 HANDLE_FIXED_TYPE(SFIXED64, Int64, int64_t);
0116 HANDLE_FIXED_TYPE(FLOAT, Float, float);
0117 HANDLE_FIXED_TYPE(DOUBLE, Double, double);
0118 #undef HANDLE_FIXED_TYPE
0119
0120 case WireFormatLite::TYPE_ENUM: {
0121 uint64_t tmp;
0122 ptr = VarintParse(ptr, &tmp);
0123 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0124 int value = tmp;
0125
0126 if (!extension.enum_validity_check.func(
0127 extension.enum_validity_check.arg, value)) {
0128 WriteVarint(number, value, metadata->mutable_unknown_fields<T>());
0129 } else if (extension.is_repeated) {
0130 AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
0131 extension.descriptor);
0132 } else {
0133 SetEnum(number, WireFormatLite::TYPE_ENUM, value,
0134 extension.descriptor);
0135 }
0136 break;
0137 }
0138
0139 case WireFormatLite::TYPE_BYTES:
0140 case WireFormatLite::TYPE_STRING: {
0141 std::string* value =
0142 extension.is_repeated
0143 ? AddString(number, WireFormatLite::TYPE_STRING,
0144 extension.descriptor)
0145 : MutableString(number, WireFormatLite::TYPE_STRING,
0146 extension.descriptor);
0147 int size = ReadSize(&ptr);
0148 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0149 return ctx->ReadString(ptr, size, value);
0150 }
0151
0152 case WireFormatLite::TYPE_GROUP: {
0153 MessageLite* value =
0154 extension.is_repeated
0155 ? AddMessage(number, WireFormatLite::TYPE_GROUP,
0156 *extension.message_info.prototype,
0157 extension.descriptor)
0158 : MutableMessage(number, WireFormatLite::TYPE_GROUP,
0159 *extension.message_info.prototype,
0160 extension.descriptor);
0161 uint32_t tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP;
0162 return ctx->ParseGroup(value, ptr, tag);
0163 }
0164
0165 case WireFormatLite::TYPE_MESSAGE: {
0166 MessageLite* value =
0167 extension.is_repeated
0168 ? AddMessage(number, WireFormatLite::TYPE_MESSAGE,
0169 *extension.message_info.prototype,
0170 extension.descriptor)
0171 : MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
0172 *extension.message_info.prototype,
0173 extension.descriptor);
0174 return ctx->ParseMessage(value, ptr);
0175 }
0176 }
0177 }
0178 return ptr;
0179 }
0180
0181 template <typename Msg, typename T>
0182 const char* ExtensionSet::ParseMessageSetItemTmpl(
0183 const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata,
0184 internal::ParseContext* ctx) {
0185 std::string payload;
0186 uint32_t type_id = 0;
0187 enum class State { kNoTag, kHasType, kHasPayload, kDone };
0188 State state = State::kNoTag;
0189
0190 while (!ctx->Done(&ptr)) {
0191 uint32_t tag = static_cast<uint8_t>(*ptr++);
0192 if (tag == WireFormatLite::kMessageSetTypeIdTag) {
0193 uint64_t tmp;
0194 ptr = ParseBigVarint(ptr, &tmp);
0195
0196 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr &&
0197 static_cast<uint32_t>(tmp) != 0);
0198 if (state == State::kNoTag) {
0199 type_id = static_cast<uint32_t>(tmp);
0200 state = State::kHasType;
0201 } else if (state == State::kHasPayload) {
0202 type_id = static_cast<uint32_t>(tmp);
0203 ExtensionInfo extension;
0204 bool was_packed_on_wire;
0205 if (!FindExtension(2, type_id, extendee, ctx, &extension,
0206 &was_packed_on_wire)) {
0207 WriteLengthDelimited(type_id, payload,
0208 metadata->mutable_unknown_fields<T>());
0209 } else {
0210 MessageLite* value =
0211 extension.is_repeated
0212 ? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE,
0213 *extension.message_info.prototype,
0214 extension.descriptor)
0215 : MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE,
0216 *extension.message_info.prototype,
0217 extension.descriptor);
0218
0219 const char* p;
0220
0221
0222
0223 ParseContext tmp_ctx(ParseContext::kSpawn, *ctx, &p, payload);
0224 GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
0225 tmp_ctx.EndedAtLimit());
0226 }
0227 state = State::kDone;
0228 }
0229 } else if (tag == WireFormatLite::kMessageSetMessageTag) {
0230 if (state == State::kHasType) {
0231 ptr = ParseFieldMaybeLazily(static_cast<uint64_t>(type_id) * 8 + 2, ptr,
0232 extendee, metadata, ctx);
0233 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
0234 state = State::kDone;
0235 } else {
0236 std::string tmp;
0237 int32_t size = ReadSize(&ptr);
0238 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0239 ptr = ctx->ReadString(ptr, size, &tmp);
0240 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0241 if (state == State::kNoTag) {
0242 payload = std::move(tmp);
0243 state = State::kHasPayload;
0244 }
0245 }
0246 } else {
0247 ptr = ReadTag(ptr - 1, &tag);
0248 if (tag == 0 || (tag & 7) == 4) {
0249 ctx->SetLastTag(tag);
0250 return ptr;
0251 }
0252 ptr = ParseField(tag, ptr, extendee, metadata, ctx);
0253 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0254 }
0255 }
0256 return ptr;
0257 }
0258
0259 }
0260 }
0261 }
0262
0263 #endif