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: kenton@google.com (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 | |
60 | void DestroyMessage(const void* message) { |
61 | static_cast<const MessageLite*>(message)->~MessageLite(); |
62 | } |
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 std::atomic<bool> init_protobuf_defaults_state{false}; |
73 | static bool InitProtobufDefaultsImpl() { |
74 | fixed_address_empty_string.DefaultConstruct(); |
75 | OnShutdownDestroyString(ptr: fixed_address_empty_string.get_mutable()); |
76 | |
77 | |
78 | init_protobuf_defaults_state.store(i: true, m: std::memory_order_release); |
79 | return true; |
80 | } |
81 | |
82 | void InitProtobufDefaultsSlow() { |
83 | static bool is_inited = InitProtobufDefaultsImpl(); |
84 | (void)is_inited; |
85 | } |
86 | // Force the initialization of the empty string. |
87 | // Normally, registration would do it, but we don't have any guarantee that |
88 | // there is any object with reflection. |
89 | PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 static std::true_type init_empty_string = |
90 | (InitProtobufDefaultsSlow(), std::true_type{}); |
91 | |
92 | size_t StringSpaceUsedExcludingSelfLong(const std::string& str) { |
93 | const void* start = &str; |
94 | const void* end = &str + 1; |
95 | if (start <= str.data() && str.data() < end) { |
96 | // The string's data is stored inside the string object itself. |
97 | return 0; |
98 | } else { |
99 | return str.capacity(); |
100 | } |
101 | } |
102 | |
103 | template <typename T> |
104 | const T& Get(const void* ptr) { |
105 | return *static_cast<const T*>(ptr); |
106 | } |
107 | |
108 | // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite. |
109 | // WireFormatLite has a very inconvenient interface with respect to template |
110 | // meta-programming. This class wraps the different named functions into |
111 | // a single Serialize / SerializeToArray interface. |
112 | template <int type> |
113 | struct PrimitiveTypeHelper; |
114 | |
115 | template <> |
116 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> { |
117 | typedef bool Type; |
118 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
119 | WireFormatLite::WriteBoolNoTag(value: Get<bool>(ptr), output); |
120 | } |
121 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
122 | return WireFormatLite::WriteBoolNoTagToArray(value: Get<Type>(ptr), target: buffer); |
123 | } |
124 | }; |
125 | |
126 | template <> |
127 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> { |
128 | typedef int32_t Type; |
129 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
130 | WireFormatLite::WriteInt32NoTag(value: Get<int32_t>(ptr), output); |
131 | } |
132 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
133 | return WireFormatLite::WriteInt32NoTagToArray(value: Get<Type>(ptr), target: buffer); |
134 | } |
135 | }; |
136 | |
137 | template <> |
138 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> { |
139 | typedef int32_t Type; |
140 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
141 | WireFormatLite::WriteSInt32NoTag(value: Get<int32_t>(ptr), output); |
142 | } |
143 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
144 | return WireFormatLite::WriteSInt32NoTagToArray(value: Get<Type>(ptr), target: buffer); |
145 | } |
146 | }; |
147 | |
148 | template <> |
149 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> { |
150 | typedef uint32_t Type; |
151 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
152 | WireFormatLite::WriteUInt32NoTag(value: Get<uint32_t>(ptr), output); |
153 | } |
154 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
155 | return WireFormatLite::WriteUInt32NoTagToArray(value: Get<Type>(ptr), target: buffer); |
156 | } |
157 | }; |
158 | template <> |
159 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> { |
160 | typedef int64_t Type; |
161 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
162 | WireFormatLite::WriteInt64NoTag(value: Get<int64_t>(ptr), output); |
163 | } |
164 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
165 | return WireFormatLite::WriteInt64NoTagToArray(value: Get<Type>(ptr), target: buffer); |
166 | } |
167 | }; |
168 | |
169 | template <> |
170 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> { |
171 | typedef int64_t Type; |
172 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
173 | WireFormatLite::WriteSInt64NoTag(value: Get<int64_t>(ptr), output); |
174 | } |
175 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
176 | return WireFormatLite::WriteSInt64NoTagToArray(value: Get<Type>(ptr), target: buffer); |
177 | } |
178 | }; |
179 | template <> |
180 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> { |
181 | typedef uint64_t Type; |
182 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
183 | WireFormatLite::WriteUInt64NoTag(value: Get<uint64_t>(ptr), output); |
184 | } |
185 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
186 | return WireFormatLite::WriteUInt64NoTagToArray(value: Get<Type>(ptr), target: buffer); |
187 | } |
188 | }; |
189 | |
190 | template <> |
191 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> { |
192 | typedef uint32_t Type; |
193 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
194 | WireFormatLite::WriteFixed32NoTag(value: Get<uint32_t>(ptr), output); |
195 | } |
196 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
197 | return WireFormatLite::WriteFixed32NoTagToArray(value: Get<Type>(ptr), target: buffer); |
198 | } |
199 | }; |
200 | |
201 | template <> |
202 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> { |
203 | typedef uint64_t Type; |
204 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
205 | WireFormatLite::WriteFixed64NoTag(value: Get<uint64_t>(ptr), output); |
206 | } |
207 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
208 | return WireFormatLite::WriteFixed64NoTagToArray(value: Get<Type>(ptr), target: buffer); |
209 | } |
210 | }; |
211 | |
212 | template <> |
213 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM> |
214 | : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {}; |
215 | |
216 | template <> |
217 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32> |
218 | : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> { |
219 | typedef int32_t Type; |
220 | }; |
221 | template <> |
222 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64> |
223 | : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> { |
224 | typedef int64_t Type; |
225 | }; |
226 | template <> |
227 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT> |
228 | : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> { |
229 | typedef float Type; |
230 | }; |
231 | template <> |
232 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE> |
233 | : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> { |
234 | typedef double Type; |
235 | }; |
236 | |
237 | template <> |
238 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> { |
239 | typedef std::string Type; |
240 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
241 | const Type& value = *static_cast<const Type*>(ptr); |
242 | output->WriteVarint32(value: value.size()); |
243 | output->WriteRawMaybeAliased(data: value.data(), size: value.size()); |
244 | } |
245 | static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { |
246 | const Type& value = *static_cast<const Type*>(ptr); |
247 | return io::CodedOutputStream::WriteStringWithSizeToArray(str: value, target: buffer); |
248 | } |
249 | }; |
250 | |
251 | template <> |
252 | struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES> |
253 | : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {}; |
254 | |
255 | // We want to serialize to both CodedOutputStream and directly into byte arrays |
256 | // without duplicating the code. In fact we might want extra output channels in |
257 | // the future. |
258 | template <typename O, int type> |
259 | struct OutputHelper; |
260 | |
261 | template <int type, typename O> |
262 | void SerializeTo(const void* ptr, O* output) { |
263 | OutputHelper<O, type>::Serialize(ptr, output); |
264 | } |
265 | |
266 | template <typename O> |
267 | void WriteTagTo(uint32_t tag, O* output) { |
268 | SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output); |
269 | } |
270 | |
271 | template <typename O> |
272 | void WriteLengthTo(uint32_t length, O* output) { |
273 | SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output); |
274 | } |
275 | |
276 | // Specialization for coded output stream |
277 | template <int type> |
278 | struct OutputHelper<io::CodedOutputStream, type> { |
279 | static void Serialize(const void* ptr, io::CodedOutputStream* output) { |
280 | PrimitiveTypeHelper<type>::Serialize(ptr, output); |
281 | } |
282 | }; |
283 | |
284 | // Specialization for writing into a plain array |
285 | struct ArrayOutput { |
286 | uint8_t* ptr; |
287 | bool is_deterministic; |
288 | }; |
289 | |
290 | template <int type> |
291 | struct OutputHelper<ArrayOutput, type> { |
292 | static void Serialize(const void* ptr, ArrayOutput* output) { |
293 | output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr); |
294 | } |
295 | }; |
296 | |
297 | void SerializeMessageNoTable(const MessageLite* msg, |
298 | io::CodedOutputStream* output) { |
299 | msg->SerializeWithCachedSizes(output); |
300 | } |
301 | |
302 | void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) { |
303 | io::ArrayOutputStream array_stream(output->ptr, INT_MAX); |
304 | io::CodedOutputStream o(&array_stream); |
305 | o.SetSerializationDeterministic(output->is_deterministic); |
306 | msg->SerializeWithCachedSizes(output: &o); |
307 | output->ptr += o.ByteCount(); |
308 | } |
309 | |
310 | // We need to use a helper class to get access to the private members |
311 | class AccessorHelper { |
312 | public: |
313 | static int Size(const RepeatedPtrFieldBase& x) { return x.size(); } |
314 | static void const* Get(const RepeatedPtrFieldBase& x, int idx) { |
315 | return x.raw_data()[idx]; |
316 | } |
317 | }; |
318 | |
319 | void SerializeNotImplemented(int field) { |
320 | GOOGLE_LOG(FATAL) << "Not implemented field number " << field; |
321 | } |
322 | |
323 | // When switching to c++11 we should make these constexpr functions |
324 | #define SERIALIZE_TABLE_OP(type, type_class) \ |
325 | ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes) |
326 | |
327 | template <int type> |
328 | bool IsNull(const void* ptr) { |
329 | return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) == |
330 | 0; |
331 | } |
332 | |
333 | template <> |
334 | bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) { |
335 | return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0; |
336 | } |
337 | |
338 | template <> |
339 | bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) { |
340 | return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0; |
341 | } |
342 | |
343 | template <> |
344 | bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) { |
345 | return Get<const MessageLite*>(ptr) == nullptr; |
346 | } |
347 | |
348 | template <> |
349 | bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) { |
350 | return Get<const MessageLite*>(ptr) == nullptr; |
351 | } |
352 | |
353 | void ExtensionSerializer(const MessageLite* extendee, const uint8_t* ptr, |
354 | uint32_t offset, uint32_t tag, uint32_t has_offset, |
355 | io::CodedOutputStream* output) { |
356 | reinterpret_cast<const ExtensionSet*>(ptr + offset) |
357 | ->SerializeWithCachedSizes(extendee, start_field_number: tag, end_field_number: has_offset, output); |
358 | } |
359 | |
360 | void UnknownFieldSerializerLite(const uint8_t* ptr, uint32_t offset, |
361 | uint32_t /*tag*/, uint32_t /*has_offset*/, |
362 | io::CodedOutputStream* output) { |
363 | output->WriteString( |
364 | str: reinterpret_cast<const InternalMetadata*>(ptr + offset) |
365 | ->unknown_fields<std::string>(default_instance: &internal::GetEmptyString)); |
366 | } |
367 | |
368 | MessageLite* DuplicateIfNonNullInternal(MessageLite* message) { |
369 | if (message) { |
370 | MessageLite* ret = message->New(); |
371 | ret->CheckTypeAndMergeFrom(other: *message); |
372 | return ret; |
373 | } else { |
374 | return nullptr; |
375 | } |
376 | } |
377 | |
378 | void GenericSwap(MessageLite* m1, MessageLite* m2) { |
379 | std::unique_ptr<MessageLite> tmp(m1->New()); |
380 | tmp->CheckTypeAndMergeFrom(other: *m1); |
381 | m1->Clear(); |
382 | m1->CheckTypeAndMergeFrom(other: *m2); |
383 | m2->Clear(); |
384 | m2->CheckTypeAndMergeFrom(other: *tmp); |
385 | } |
386 | |
387 | // Returns a message owned by this Arena. This may require Own()ing or |
388 | // duplicating the message. |
389 | MessageLite* GetOwnedMessageInternal(Arena* message_arena, |
390 | MessageLite* submessage, |
391 | Arena* submessage_arena) { |
392 | GOOGLE_DCHECK(Arena::InternalGetOwningArena(submessage) == submessage_arena); |
393 | GOOGLE_DCHECK(message_arena != submessage_arena); |
394 | GOOGLE_DCHECK_EQ(submessage_arena, nullptr); |
395 | if (message_arena != nullptr && submessage_arena == nullptr) { |
396 | message_arena->Own(object: submessage); |
397 | return submessage; |
398 | } else { |
399 | MessageLite* ret = submessage->New(arena: message_arena); |
400 | ret->CheckTypeAndMergeFrom(other: *submessage); |
401 | return ret; |
402 | } |
403 | } |
404 | |
405 | } // namespace internal |
406 | } // namespace protobuf |
407 | } // namespace google |
408 | |
409 | #include <google/protobuf/port_undef.inc> |
410 | |