1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 // Author: kenton@google.com (Kenton Varda)
9 // Based on original Protocol Buffers design by
10 // Sanjay Ghemawat, Jeff Dean, and others.
11 //
12 // Contains classes used to keep track of unrecognized fields seen while
13 // parsing a protocol message.
14
15 #ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
16 #define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
17
18 #include <assert.h>
19
20 #include <atomic>
21 #include <string>
22
23 #include "google/protobuf/stubs/common.h"
24 #include "absl/log/absl_check.h"
25 #include "absl/strings/cord.h"
26 #include "absl/strings/string_view.h"
27 #include "google/protobuf/arena.h"
28 #include "google/protobuf/io/coded_stream.h"
29 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
30 #include "google/protobuf/message_lite.h"
31 #include "google/protobuf/metadata_lite.h"
32 #include "google/protobuf/parse_context.h"
33 #include "google/protobuf/port.h"
34 #include "google/protobuf/repeated_field.h"
35
36 // Must be included last.
37 #include "google/protobuf/port_def.inc"
38
39 #ifdef SWIG
40 #error "You cannot SWIG proto headers"
41 #endif
42
43 namespace google {
44 namespace protobuf {
45 namespace internal {
46 class InternalMetadata; // metadata_lite.h
47 class WireFormat; // wire_format.h
48 class MessageSetFieldSkipperUsingCord;
49 // extension_set_heavy.cc
50 class UnknownFieldParserHelper;
51 struct UnknownFieldSetTestPeer;
52
53 #if defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE)
54 using UFSStringView = absl::string_view;
55 #else
56 using UFSStringView = const std::string&;
57 #endif
58 } // namespace internal
59
60 class Message; // message.h
61
62 // Represents one field in an UnknownFieldSet.
63 class PROTOBUF_EXPORT UnknownField {
64 public:
65 enum Type {
66 TYPE_VARINT,
67 TYPE_FIXED32,
68 TYPE_FIXED64,
69 TYPE_LENGTH_DELIMITED,
70 TYPE_GROUP
71 };
72
73 // The field's field number, as seen on the wire.
74 inline int number() const;
75
76 // The field type.
77 inline Type type() const;
78
79 // Accessors -------------------------------------------------------
80 // Each method works only for UnknownFields of the corresponding type.
81
82 inline uint64_t varint() const;
83 inline uint32_t fixed32() const;
84 inline uint64_t fixed64() const;
85 inline internal::UFSStringView length_delimited() const;
86 inline const UnknownFieldSet& group() const;
87
88 inline void set_varint(uint64_t value);
89 inline void set_fixed32(uint32_t value);
90 inline void set_fixed64(uint64_t value);
91 inline void set_length_delimited(absl::string_view value);
92 // template to avoid ambiguous overload resolution.
93 template <int&...>
94 inline void set_length_delimited(std::string&& value);
95 inline void set_length_delimited(const absl::Cord& value);
96 #if !defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE)
97 inline std::string* mutable_length_delimited();
98 #endif // PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE
99 inline UnknownFieldSet* mutable_group();
100
101 inline size_t GetLengthDelimitedSize() const;
102 uint8_t* InternalSerializeLengthDelimitedNoTag(
103 uint8_t* target, io::EpsCopyOutputStream* stream) const;
104
105 private:
106 friend class UnknownFieldSet;
107
108 // If this UnknownField contains a pointer, delete it.
109 void Delete();
110
111 // Make a deep copy of any pointers in this UnknownField.
112 UnknownField DeepCopy(Arena* arena) const;
113
114 // Set the wire type of this UnknownField. Should only be used when this
115 // UnknownField is being created.
116 inline void SetType(Type type);
117
118 uint32_t number_;
119 uint32_t type_;
120 union {
121 uint64_t varint_;
122 uint32_t fixed32_;
123 uint64_t fixed64_;
124 std::string* string_value;
125 UnknownFieldSet* group_;
126 } data_;
127 };
128
129 // An UnknownFieldSet contains fields that were encountered while parsing a
130 // message but were not defined by its type. Keeping track of these can be
131 // useful, especially in that they may be written if the message is serialized
132 // again without being cleared in between. This means that software which
133 // simply receives messages and forwards them to other servers does not need
134 // to be updated every time a new field is added to the message definition.
135 //
136 // To get the UnknownFieldSet attached to any message, call
137 // Reflection::GetUnknownFields().
138 //
139 // This class is necessarily tied to the protocol buffer wire format, unlike
140 // the Reflection interface which is independent of any serialization scheme.
141 class PROTOBUF_EXPORT UnknownFieldSet {
142 public:
143 constexpr UnknownFieldSet();
144 UnknownFieldSet(const UnknownFieldSet&) = delete;
145 UnknownFieldSet& operator=(const UnknownFieldSet&) = delete;
146 ~UnknownFieldSet();
147
148 // Remove all fields.
149 inline void Clear();
150
151 // Remove all fields and deallocate internal data objects
152 void ClearAndFreeMemory();
153
154 // Is this set empty?
155 inline bool empty() const;
156
157 // Merge the contents of some other UnknownFieldSet with this one.
158 void MergeFrom(const UnknownFieldSet& other);
159
160 // Similar to above, but this function will destroy the contents of other.
161 void MergeFromAndDestroy(UnknownFieldSet* other);
162
163 // Merge the contents an UnknownFieldSet with the UnknownFieldSet in
164 // *metadata, if there is one. If *metadata doesn't have an UnknownFieldSet
165 // then add one to it and make it be a copy of the first arg.
166 static void MergeToInternalMetadata(const UnknownFieldSet& other,
167 internal::InternalMetadata* metadata);
168
169 // Swaps the contents of some other UnknownFieldSet with this one.
170 inline void Swap(UnknownFieldSet* x);
171
172 // Computes (an estimate of) the total number of bytes currently used for
173 // storing the unknown fields in memory. Does NOT include
174 // sizeof(*this) in the calculation.
175 size_t SpaceUsedExcludingSelfLong() const;
176
SpaceUsedExcludingSelf()177 int SpaceUsedExcludingSelf() const {
178 return internal::ToIntSize(SpaceUsedExcludingSelfLong());
179 }
180
181 // Version of SpaceUsed() including sizeof(*this).
182 size_t SpaceUsedLong() const;
183
SpaceUsed()184 int SpaceUsed() const { return internal::ToIntSize(SpaceUsedLong()); }
185
186 // Returns the number of fields present in the UnknownFieldSet.
187 inline int field_count() const;
188 // Get a field in the set, where 0 <= index < field_count(). The fields
189 // appear in the order in which they were added.
190 inline const UnknownField& field(int index) const;
191 // Get a mutable pointer to a field in the set, where
192 // 0 <= index < field_count(). The fields appear in the order in which
193 // they were added.
194 inline UnknownField* mutable_field(int index);
195
196 // Adding fields ---------------------------------------------------
197
198 void AddVarint(int number, uint64_t value);
199 void AddFixed32(int number, uint32_t value);
200 void AddFixed64(int number, uint64_t value);
201 void AddLengthDelimited(int number, absl::string_view value);
202 // template to avoid ambiguous overload resolution.
203 template <int&...>
204 void AddLengthDelimited(int number, std::string&& value);
205 void AddLengthDelimited(int number, const absl::Cord& value);
206
207 #if !defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE)
208 std::string* AddLengthDelimited(int number);
209 #endif // PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE
210 UnknownFieldSet* AddGroup(int number);
211
212 // Adds an unknown field from another set.
213 void AddField(const UnknownField& field);
214
215 // Delete fields with indices in the range [start .. start+num-1].
216 // Caution: implementation moves all fields with indices [start+num .. ].
217 void DeleteSubrange(int start, int num);
218
219 // Delete all fields with a specific field number. The order of left fields
220 // is preserved.
221 // Caution: implementation moves all fields after the first deleted field.
222 void DeleteByNumber(int number);
223
224 // Parsing helpers -------------------------------------------------
225 // These work exactly like the similarly-named methods of Message.
226
227 bool MergeFromCodedStream(io::CodedInputStream* input);
228 bool ParseFromCodedStream(io::CodedInputStream* input);
229 bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
230 bool ParseFromArray(const void* data, int size);
ParseFromString(const absl::string_view data)231 inline bool ParseFromString(const absl::string_view data) {
232 return ParseFromArray(data.data(), static_cast<int>(data.size()));
233 }
234
235 // Merges this message's unknown field data (if any). This works whether
236 // the message is a lite or full proto (for legacy reasons, lite and full
237 // return different types for MessageType::unknown_fields()).
238 template <typename MessageType>
239 bool MergeFromMessage(const MessageType& message);
240
241 // Serialization.
242 bool SerializeToString(std::string* output) const;
243 bool SerializeToCord(absl::Cord* output) const;
244 bool SerializeToCodedStream(io::CodedOutputStream* output) const;
245 static const UnknownFieldSet& default_instance();
246
UnknownFieldSet(internal::InternalVisibility,Arena * arena)247 UnknownFieldSet(internal::InternalVisibility, Arena* arena)
248 : UnknownFieldSet(arena) {}
249
250 private:
251 friend internal::WireFormat;
252 friend internal::UnknownFieldParserHelper;
253 friend internal::UnknownFieldSetTestPeer;
254
255 #if defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE)
256 std::string* AddLengthDelimited(int number);
257 #endif // PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE
258
259 using InternalArenaConstructable_ = void;
260 using DestructorSkippable_ = void;
261
262 friend class google::protobuf::Arena;
UnknownFieldSet(Arena * arena)263 explicit UnknownFieldSet(Arena* arena) : fields_(arena) {}
264
arena()265 Arena* arena() { return fields_.GetArena(); }
266
267 void ClearFallback();
268 void SwapSlow(UnknownFieldSet* other);
269
270 template <typename MessageType,
271 typename std::enable_if<
272 std::is_base_of<Message, MessageType>::value, int>::type = 0>
InternalMergeFromMessage(const MessageType & message)273 bool InternalMergeFromMessage(const MessageType& message) {
274 MergeFrom(message.GetReflection()->GetUnknownFields(message));
275 return true;
276 }
277
278 template <typename MessageType,
279 typename std::enable_if<
280 std::is_base_of<MessageLite, MessageType>::value &&
281 !std::is_base_of<Message, MessageType>::value,
282 int>::type = 0>
InternalMergeFromMessage(const MessageType & message)283 bool InternalMergeFromMessage(const MessageType& message) {
284 const auto& unknown_fields = message.unknown_fields();
285 io::ArrayInputStream array_stream(unknown_fields.data(),
286 unknown_fields.size());
287 io::CodedInputStream coded_stream(&array_stream);
288 return MergeFromCodedStream(&coded_stream);
289 }
290
291 RepeatedField<UnknownField> fields_;
292 };
293
294 namespace internal {
295
WriteVarint(uint32_t num,uint64_t val,UnknownFieldSet * unknown)296 inline void WriteVarint(uint32_t num, uint64_t val, UnknownFieldSet* unknown) {
297 unknown->AddVarint(num, val);
298 }
WriteLengthDelimited(uint32_t num,absl::string_view val,UnknownFieldSet * unknown)299 inline void WriteLengthDelimited(uint32_t num, absl::string_view val,
300 UnknownFieldSet* unknown) {
301 unknown->AddLengthDelimited(num, val);
302 }
303
304 PROTOBUF_EXPORT
305 const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr,
306 ParseContext* ctx);
307 PROTOBUF_EXPORT
308 const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown,
309 const char* ptr, ParseContext* ctx);
310
311 } // namespace internal
312
313 // ===================================================================
314 // inline implementations
315
316 constexpr UnknownFieldSet::UnknownFieldSet() = default;
317
~UnknownFieldSet()318 inline UnknownFieldSet::~UnknownFieldSet() { Clear(); }
319
default_instance()320 inline const UnknownFieldSet& UnknownFieldSet::default_instance() {
321 PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT static const UnknownFieldSet
322 instance;
323 return instance;
324 }
325
ClearAndFreeMemory()326 inline void UnknownFieldSet::ClearAndFreeMemory() { Clear(); }
327
Clear()328 inline void UnknownFieldSet::Clear() {
329 if (!fields_.empty()) {
330 ClearFallback();
331 }
332 }
333
empty()334 inline bool UnknownFieldSet::empty() const { return fields_.empty(); }
335
Swap(UnknownFieldSet * x)336 inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
337 if (arena() == x->arena()) {
338 fields_.Swap(&x->fields_);
339 } else {
340 // We might need to do a deep copy, so use Merge instead
341 SwapSlow(x);
342 }
343 }
344
field_count()345 inline int UnknownFieldSet::field_count() const {
346 return static_cast<int>(fields_.size());
347 }
field(int index)348 inline const UnknownField& UnknownFieldSet::field(int index) const {
349 return (fields_)[static_cast<size_t>(index)];
350 }
mutable_field(int index)351 inline UnknownField* UnknownFieldSet::mutable_field(int index) {
352 return &(fields_)[static_cast<size_t>(index)];
353 }
354
AddLengthDelimited(int number,const absl::string_view value)355 inline void UnknownFieldSet::AddLengthDelimited(int number,
356 const absl::string_view value) {
357 AddLengthDelimited(number)->assign(value.data(), value.size());
358 }
359
number()360 inline int UnknownField::number() const { return static_cast<int>(number_); }
type()361 inline UnknownField::Type UnknownField::type() const {
362 return static_cast<Type>(type_);
363 }
364
varint()365 inline uint64_t UnknownField::varint() const {
366 assert(type() == TYPE_VARINT);
367 return data_.varint_;
368 }
fixed32()369 inline uint32_t UnknownField::fixed32() const {
370 assert(type() == TYPE_FIXED32);
371 return data_.fixed32_;
372 }
fixed64()373 inline uint64_t UnknownField::fixed64() const {
374 assert(type() == TYPE_FIXED64);
375 return data_.fixed64_;
376 }
length_delimited()377 inline internal::UFSStringView UnknownField::length_delimited() const {
378 assert(type() == TYPE_LENGTH_DELIMITED);
379 return *data_.string_value;
380 }
group()381 inline const UnknownFieldSet& UnknownField::group() const {
382 assert(type() == TYPE_GROUP);
383 return *data_.group_;
384 }
385
set_varint(uint64_t value)386 inline void UnknownField::set_varint(uint64_t value) {
387 assert(type() == TYPE_VARINT);
388 data_.varint_ = value;
389 }
set_fixed32(uint32_t value)390 inline void UnknownField::set_fixed32(uint32_t value) {
391 assert(type() == TYPE_FIXED32);
392 data_.fixed32_ = value;
393 }
set_fixed64(uint64_t value)394 inline void UnknownField::set_fixed64(uint64_t value) {
395 assert(type() == TYPE_FIXED64);
396 data_.fixed64_ = value;
397 }
set_length_delimited(const absl::string_view value)398 inline void UnknownField::set_length_delimited(const absl::string_view value) {
399 assert(type() == TYPE_LENGTH_DELIMITED);
400 data_.string_value->assign(value.data(), value.size());
401 }
402 template <int&...>
set_length_delimited(std::string && value)403 inline void UnknownField::set_length_delimited(std::string&& value) {
404 assert(type() == TYPE_LENGTH_DELIMITED);
405 *data_.string_value = std::move(value);
406 }
set_length_delimited(const absl::Cord & value)407 inline void UnknownField::set_length_delimited(const absl::Cord& value) {
408 assert(type() == TYPE_LENGTH_DELIMITED);
409 absl::CopyCordToString(value, data_.string_value);
410 }
411 #if !defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE)
mutable_length_delimited()412 inline std::string* UnknownField::mutable_length_delimited() {
413 assert(type() == TYPE_LENGTH_DELIMITED);
414 return data_.string_value;
415 }
416 #endif // PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE
mutable_group()417 inline UnknownFieldSet* UnknownField::mutable_group() {
418 assert(type() == TYPE_GROUP);
419 return data_.group_;
420 }
421 template <typename MessageType>
MergeFromMessage(const MessageType & message)422 bool UnknownFieldSet::MergeFromMessage(const MessageType& message) {
423 // SFINAE will route to the right version.
424 return InternalMergeFromMessage(message);
425 }
426
GetLengthDelimitedSize()427 inline size_t UnknownField::GetLengthDelimitedSize() const {
428 ABSL_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
429 return data_.string_value->size();
430 }
431
SetType(Type type)432 inline void UnknownField::SetType(Type type) { type_ = type; }
433
434 extern template void UnknownFieldSet::AddLengthDelimited(int, std::string&&);
435
436 namespace internal {
437
438 // Add specialization of InternalMetadata::Container to provide arena support.
439 template <>
440 struct InternalMetadata::Container<UnknownFieldSet>
441 : public InternalMetadata::ContainerBase {
442 UnknownFieldSet unknown_fields;
443
444 explicit Container(Arena* input_arena)
445 : unknown_fields(InternalVisibility{}, input_arena) {}
446
447 using InternalArenaConstructable_ = void;
448 using DestructorSkippable_ = void;
449 };
450 } // namespace internal
451
452 } // namespace protobuf
453 } // namespace google
454
455 #include "google/protobuf/port_undef.inc"
456 #endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
457