xref: /aosp_15_r20/external/cronet/third_party/protobuf/src/google/protobuf/generated_message_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: [email protected] (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/generated_message_util.h>
36 
37 #include <atomic>
38 #include <limits>
39 #include <vector>
40 
41 #include <google/protobuf/io/coded_stream.h>
42 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
43 #include <google/protobuf/arenastring.h>
44 #include <google/protobuf/extension_set.h>
45 #include <google/protobuf/message_lite.h>
46 #include <google/protobuf/metadata_lite.h>
47 #include <google/protobuf/repeated_field.h>
48 #include <google/protobuf/wire_format_lite.h>
49 
50 // Must be included last
51 #include <google/protobuf/port_def.inc>
52 
53 PROTOBUF_PRAGMA_INIT_SEG
54 
55 
56 namespace google {
57 namespace protobuf {
58 namespace internal {
59 
DestroyMessage(const void * message)60 void DestroyMessage(const void* message) {
61   static_cast<const MessageLite*>(message)->~MessageLite();
62 }
DestroyString(const void * s)63 void DestroyString(const void* s) {
64   static_cast<const std::string*>(s)->~basic_string();
65 }
66 
67 PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
68     PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExplicitlyConstructedArenaString
69         fixed_address_empty_string{};  // NOLINT
70 
71 
72 PROTOBUF_CONSTINIT bool init_protobuf_defaults_state{false};
InitProtobufDefaultsSlow()73 void InitProtobufDefaultsSlow() {
74   fixed_address_empty_string.DefaultConstruct();
75   init_protobuf_defaults_state = true;
76 }
77 // Force the initialization of the empty string.
78 // Normally, registration would do it, but we don't have any guarantee that
79 // there is any object with reflection.
80 PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 static std::true_type init_empty_string =
81     (InitProtobufDefaults(), std::true_type{});
82 
GetEmptyString()83 const std::string& GetEmptyString() {
84   InitProtobufDefaults();
85   return GetEmptyStringAlreadyInited();
86 }
87 
StringSpaceUsedExcludingSelfLong(const std::string & str)88 size_t StringSpaceUsedExcludingSelfLong(const std::string& str) {
89   const void* start = &str;
90   const void* end = &str + 1;
91   if (start <= str.data() && str.data() < end) {
92     // The string's data is stored inside the string object itself.
93     return 0;
94   } else {
95     return str.capacity();
96   }
97 }
98 
99 template <typename T>
Get(const void * ptr)100 const T& Get(const void* ptr) {
101   return *static_cast<const T*>(ptr);
102 }
103 
104 // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
105 // WireFormatLite has a very inconvenient interface with respect to template
106 // meta-programming. This class wraps the different named functions into
107 // a single Serialize / SerializeToArray interface.
108 template <int type>
109 struct PrimitiveTypeHelper;
110 
111 template <>
112 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
113   typedef bool Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper114   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
115     WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
116   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper117   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
118     return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
119   }
120 };
121 
122 template <>
123 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
124   typedef int32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper125   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
126     WireFormatLite::WriteInt32NoTag(Get<int32_t>(ptr), output);
127   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper128   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
129     return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
130   }
131 };
132 
133 template <>
134 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
135   typedef int32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper136   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
137     WireFormatLite::WriteSInt32NoTag(Get<int32_t>(ptr), output);
138   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper139   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
140     return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
141   }
142 };
143 
144 template <>
145 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
146   typedef uint32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper147   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
148     WireFormatLite::WriteUInt32NoTag(Get<uint32_t>(ptr), output);
149   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper150   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
151     return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
152   }
153 };
154 template <>
155 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
156   typedef int64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper157   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
158     WireFormatLite::WriteInt64NoTag(Get<int64_t>(ptr), output);
159   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper160   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
161     return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
162   }
163 };
164 
165 template <>
166 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
167   typedef int64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper168   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
169     WireFormatLite::WriteSInt64NoTag(Get<int64_t>(ptr), output);
170   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper171   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
172     return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
173   }
174 };
175 template <>
176 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
177   typedef uint64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper178   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
179     WireFormatLite::WriteUInt64NoTag(Get<uint64_t>(ptr), output);
180   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper181   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
182     return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
183   }
184 };
185 
186 template <>
187 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
188   typedef uint32_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper189   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
190     WireFormatLite::WriteFixed32NoTag(Get<uint32_t>(ptr), output);
191   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper192   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
193     return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
194   }
195 };
196 
197 template <>
198 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
199   typedef uint64_t Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper200   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
201     WireFormatLite::WriteFixed64NoTag(Get<uint64_t>(ptr), output);
202   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper203   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
204     return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
205   }
206 };
207 
208 template <>
209 struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
210     : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
211 
212 template <>
213 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
214     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
215   typedef int32_t Type;
216 };
217 template <>
218 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
219     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
220   typedef int64_t Type;
221 };
222 template <>
223 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
224     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
225   typedef float Type;
226 };
227 template <>
228 struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
229     : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
230   typedef double Type;
231 };
232 
233 template <>
234 struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
235   typedef std::string Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper236   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
237     const Type& value = *static_cast<const Type*>(ptr);
238     output->WriteVarint32(value.size());
239     output->WriteRawMaybeAliased(value.data(), value.size());
240   }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper241   static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) {
242     const Type& value = *static_cast<const Type*>(ptr);
243     return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
244   }
245 };
246 
247 template <>
248 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
249     : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
250 
251 // We want to serialize to both CodedOutputStream and directly into byte arrays
252 // without duplicating the code. In fact we might want extra output channels in
253 // the future.
254 template <typename O, int type>
255 struct OutputHelper;
256 
257 template <int type, typename O>
SerializeTo(const void * ptr,O * output)258 void SerializeTo(const void* ptr, O* output) {
259   OutputHelper<O, type>::Serialize(ptr, output);
260 }
261 
262 template <typename O>
WriteTagTo(uint32_t tag,O * output)263 void WriteTagTo(uint32_t tag, O* output) {
264   SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
265 }
266 
267 template <typename O>
WriteLengthTo(uint32_t length,O * output)268 void WriteLengthTo(uint32_t length, O* output) {
269   SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
270 }
271 
272 // Specialization for coded output stream
273 template <int type>
274 struct OutputHelper<io::CodedOutputStream, type> {
Serializegoogle::protobuf::internal::OutputHelper275   static void Serialize(const void* ptr, io::CodedOutputStream* output) {
276     PrimitiveTypeHelper<type>::Serialize(ptr, output);
277   }
278 };
279 
280 // Specialization for writing into a plain array
281 struct ArrayOutput {
282   uint8_t* ptr;
283   bool is_deterministic;
284 };
285 
286 template <int type>
287 struct OutputHelper<ArrayOutput, type> {
Serializegoogle::protobuf::internal::OutputHelper288   static void Serialize(const void* ptr, ArrayOutput* output) {
289     output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
290   }
291 };
292 
SerializeMessageNoTable(const MessageLite * msg,io::CodedOutputStream * output)293 void SerializeMessageNoTable(const MessageLite* msg,
294                              io::CodedOutputStream* output) {
295   msg->SerializeWithCachedSizes(output);
296 }
297 
SerializeMessageNoTable(const MessageLite * msg,ArrayOutput * output)298 void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
299   io::ArrayOutputStream array_stream(output->ptr, INT_MAX);
300   io::CodedOutputStream o(&array_stream);
301   o.SetSerializationDeterministic(output->is_deterministic);
302   msg->SerializeWithCachedSizes(&o);
303   output->ptr += o.ByteCount();
304 }
305 
306 // We need to use a helper class to get access to the private members
307 class AccessorHelper {
308  public:
Size(const RepeatedPtrFieldBase & x)309   static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
Get(const RepeatedPtrFieldBase & x,int idx)310   static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
311     return x.raw_data()[idx];
312   }
313 };
314 
SerializeNotImplemented(int field)315 void SerializeNotImplemented(int field) {
316   GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
317 }
318 
319 // When switching to c++11 we should make these constexpr functions
320 #define SERIALIZE_TABLE_OP(type, type_class) \
321   ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
322 
323 template <int type>
IsNull(const void * ptr)324 bool IsNull(const void* ptr) {
325   return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
326          0;
327 }
328 
329 template <>
IsNull(const void * ptr)330 bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
331   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
332 }
333 
334 template <>
IsNull(const void * ptr)335 bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
336   return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
337 }
338 
339 template <>
IsNull(const void * ptr)340 bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
341   return Get<const MessageLite*>(ptr) == nullptr;
342 }
343 
344 template <>
IsNull(const void * ptr)345 bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
346   return Get<const MessageLite*>(ptr) == nullptr;
347 }
348 
ExtensionSerializer(const MessageLite * extendee,const uint8_t * ptr,uint32_t offset,uint32_t tag,uint32_t has_offset,io::CodedOutputStream * output)349 void ExtensionSerializer(const MessageLite* extendee, const uint8_t* ptr,
350                          uint32_t offset, uint32_t tag, uint32_t has_offset,
351                          io::CodedOutputStream* output) {
352   reinterpret_cast<const ExtensionSet*>(ptr + offset)
353       ->SerializeWithCachedSizes(extendee, tag, has_offset, output);
354 }
355 
UnknownFieldSerializerLite(const uint8_t * ptr,uint32_t offset,uint32_t,uint32_t,io::CodedOutputStream * output)356 void UnknownFieldSerializerLite(const uint8_t* ptr, uint32_t offset,
357                                 uint32_t /*tag*/, uint32_t /*has_offset*/,
358                                 io::CodedOutputStream* output) {
359   output->WriteString(
360       reinterpret_cast<const InternalMetadata*>(ptr + offset)
361           ->unknown_fields<std::string>(&internal::GetEmptyString));
362 }
363 
DuplicateIfNonNullInternal(MessageLite * message)364 MessageLite* DuplicateIfNonNullInternal(MessageLite* message) {
365   if (message) {
366     MessageLite* ret = message->New();
367     ret->CheckTypeAndMergeFrom(*message);
368     return ret;
369   } else {
370     return nullptr;
371   }
372 }
373 
GenericSwap(MessageLite * m1,MessageLite * m2)374 void GenericSwap(MessageLite* m1, MessageLite* m2) {
375   std::unique_ptr<MessageLite> tmp(m1->New());
376   tmp->CheckTypeAndMergeFrom(*m1);
377   m1->Clear();
378   m1->CheckTypeAndMergeFrom(*m2);
379   m2->Clear();
380   m2->CheckTypeAndMergeFrom(*tmp);
381 }
382 
383 // Returns a message owned by this Arena.  This may require Own()ing or
384 // duplicating the message.
GetOwnedMessageInternal(Arena * message_arena,MessageLite * submessage,Arena * submessage_arena)385 MessageLite* GetOwnedMessageInternal(Arena* message_arena,
386                                      MessageLite* submessage,
387                                      Arena* submessage_arena) {
388   GOOGLE_DCHECK(Arena::InternalGetOwningArena(submessage) == submessage_arena);
389   GOOGLE_DCHECK(message_arena != submessage_arena);
390   GOOGLE_DCHECK_EQ(submessage_arena, nullptr);
391   if (message_arena != nullptr && submessage_arena == nullptr) {
392     message_arena->Own(submessage);
393     return submessage;
394   } else {
395     MessageLite* ret = submessage->New(message_arena);
396     ret->CheckTypeAndMergeFrom(*submessage);
397     return ret;
398   }
399 }
400 
401 }  // namespace internal
402 }  // namespace protobuf
403 }  // namespace google
404 
405 #include <google/protobuf/port_undef.inc>
406