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