blob: 5d0fc42b8e0191bb80952c5549b2196e93259b50 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// 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// This header defines the RepeatedFieldRef class template used to access
32// repeated fields with protobuf reflection API.
33#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
34#define GOOGLE_PROTOBUF_REFLECTION_H__
35
36#include <memory>
Brian Silverman9c614bc2016-02-15 20:20:02 -050037
38#include <google/protobuf/message.h>
39#include <google/protobuf/generated_enum_util.h>
40
41namespace google {
42namespace protobuf {
43namespace internal {
44template<typename T, typename Enable = void>
45struct RefTypeTraits;
46} // namespace internal
47
48template<typename T>
49RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
50 const Message& message, const FieldDescriptor* field) const {
51 return RepeatedFieldRef<T>(message, field);
52}
53
54template<typename T>
55MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
56 Message* message, const FieldDescriptor* field) const {
57 return MutableRepeatedFieldRef<T>(message, field);
58}
59
60// RepeatedFieldRef definition for non-message types.
61template<typename T>
62class RepeatedFieldRef<
Austin Schuh40c16522018-10-28 20:27:54 -070063 T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -050064 typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
65 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
66
67 public:
68 bool empty() const {
69 return accessor_->IsEmpty(data_);
70 }
71 int size() const {
72 return accessor_->Size(data_);
73 }
74 T Get(int index) const {
75 return accessor_->template Get<T>(data_, index);
76 }
77
78 typedef IteratorType iterator;
79 typedef IteratorType const_iterator;
Austin Schuh40c16522018-10-28 20:27:54 -070080 typedef T value_type;
81 typedef T& reference;
82 typedef const T& const_reference;
83 typedef int size_type;
84 typedef ptrdiff_t difference_type;
85
Brian Silverman9c614bc2016-02-15 20:20:02 -050086 iterator begin() const {
87 return iterator(data_, accessor_, true);
88 }
89 iterator end() const {
90 return iterator(data_, accessor_, false);
91 }
92
93 private:
94 friend class Reflection;
95 RepeatedFieldRef(
96 const Message& message,
97 const FieldDescriptor* field) {
98 const Reflection* reflection = message.GetReflection();
99 data_ = reflection->RepeatedFieldData(
100 const_cast<Message*>(&message), field,
101 internal::RefTypeTraits<T>::cpp_type, NULL);
102 accessor_ = reflection->RepeatedFieldAccessor(field);
103 }
104
105 const void* data_;
106 const AccessorType* accessor_;
107};
108
109// MutableRepeatedFieldRef definition for non-message types.
110template<typename T>
111class MutableRepeatedFieldRef<
Austin Schuh40c16522018-10-28 20:27:54 -0700112 T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500113 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
114
115 public:
116 bool empty() const {
117 return accessor_->IsEmpty(data_);
118 }
119 int size() const {
120 return accessor_->Size(data_);
121 }
122 T Get(int index) const {
123 return accessor_->template Get<T>(data_, index);
124 }
125
126 void Set(int index, const T& value) const {
127 accessor_->template Set<T>(data_, index, value);
128 }
129 void Add(const T& value) const {
130 accessor_->template Add<T>(data_, value);
131 }
132 void RemoveLast() const {
133 accessor_->RemoveLast(data_);
134 }
135 void SwapElements(int index1, int index2) const {
136 accessor_->SwapElements(data_, index1, index2);
137 }
138 void Clear() const {
139 accessor_->Clear(data_);
140 }
141
142 void Swap(const MutableRepeatedFieldRef& other) const {
143 accessor_->Swap(data_, other.accessor_, other.data_);
144 }
145
146 template<typename Container>
147 void MergeFrom(const Container& container) const {
148 typedef typename Container::const_iterator Iterator;
149 for (Iterator it = container.begin(); it != container.end(); ++it) {
150 Add(*it);
151 }
152 }
153 template<typename Container>
154 void CopyFrom(const Container& container) const {
155 Clear();
156 MergeFrom(container);
157 }
158
159 private:
160 friend class Reflection;
161 MutableRepeatedFieldRef(
162 Message* message,
163 const FieldDescriptor* field) {
164 const Reflection* reflection = message->GetReflection();
165 data_ = reflection->RepeatedFieldData(
166 message, field, internal::RefTypeTraits<T>::cpp_type, NULL);
167 accessor_ = reflection->RepeatedFieldAccessor(field);
168 }
169
170 void* data_;
171 const AccessorType* accessor_;
172};
173
174// RepeatedFieldRef definition for message types.
175template<typename T>
176class RepeatedFieldRef<
Austin Schuh40c16522018-10-28 20:27:54 -0700177 T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500178 typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
179 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
180
181 public:
182 bool empty() const {
183 return accessor_->IsEmpty(data_);
184 }
185 int size() const {
186 return accessor_->Size(data_);
187 }
188 // This method returns a reference to the underlying message object if it
189 // exists. If a message object doesn't exist (e.g., data stored in serialized
190 // form), scratch_space will be filled with the data and a reference to it
191 // will be returned.
192 //
193 // Example:
194 // RepeatedFieldRef<Message> h = ...
195 // unique_ptr<Message> scratch_space(h.NewMessage());
196 // const Message& item = h.Get(index, scratch_space.get());
197 const T& Get(int index, T* scratch_space) const {
198 return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
199 }
200 // Create a new message of the same type as the messages stored in this
201 // repeated field. Caller takes ownership of the returned object.
202 T* NewMessage() const {
203 return static_cast<T*>(default_instance_->New());
204 }
205
206 typedef IteratorType iterator;
207 typedef IteratorType const_iterator;
Austin Schuh40c16522018-10-28 20:27:54 -0700208 typedef T value_type;
209 typedef T& reference;
210 typedef const T& const_reference;
211 typedef int size_type;
212 typedef ptrdiff_t difference_type;
213
Brian Silverman9c614bc2016-02-15 20:20:02 -0500214 iterator begin() const {
215 return iterator(data_, accessor_, true, NewMessage());
216 }
217 iterator end() const {
Austin Schuh40c16522018-10-28 20:27:54 -0700218 // The end iterator must not be dereferenced, no need for scratch space.
219 return iterator(data_, accessor_, false, nullptr);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500220 }
221
222 private:
223 friend class Reflection;
224 RepeatedFieldRef(
225 const Message& message,
226 const FieldDescriptor* field) {
227 const Reflection* reflection = message.GetReflection();
228 data_ = reflection->RepeatedFieldData(
229 const_cast<Message*>(&message), field,
230 internal::RefTypeTraits<T>::cpp_type,
231 internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
232 accessor_ = reflection->RepeatedFieldAccessor(field);
233 default_instance_ =
234 reflection->GetMessageFactory()->GetPrototype(field->message_type());
235 }
236
237 const void* data_;
238 const AccessorType* accessor_;
239 const Message* default_instance_;
240};
241
242// MutableRepeatedFieldRef definition for message types.
243template<typename T>
244class MutableRepeatedFieldRef<
Austin Schuh40c16522018-10-28 20:27:54 -0700245 T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500246 typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
247
248 public:
249 bool empty() const {
250 return accessor_->IsEmpty(data_);
251 }
252 int size() const {
253 return accessor_->Size(data_);
254 }
255 // See comments for RepeatedFieldRef<Message>::Get()
256 const T& Get(int index, T* scratch_space) const {
257 return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
258 }
259 // Create a new message of the same type as the messages stored in this
260 // repeated field. Caller takes ownership of the returned object.
261 T* NewMessage() const {
262 return static_cast<T*>(default_instance_->New());
263 }
264
265 void Set(int index, const T& value) const {
266 accessor_->Set(data_, index, &value);
267 }
268 void Add(const T& value) const {
269 accessor_->Add(data_, &value);
270 }
271 void RemoveLast() const {
272 accessor_->RemoveLast(data_);
273 }
274 void SwapElements(int index1, int index2) const {
275 accessor_->SwapElements(data_, index1, index2);
276 }
277 void Clear() const {
278 accessor_->Clear(data_);
279 }
280
281 void Swap(const MutableRepeatedFieldRef& other) const {
282 accessor_->Swap(data_, other.accessor_, other.data_);
283 }
284
285 template<typename Container>
286 void MergeFrom(const Container& container) const {
287 typedef typename Container::const_iterator Iterator;
288 for (Iterator it = container.begin(); it != container.end(); ++it) {
289 Add(*it);
290 }
291 }
292 template<typename Container>
293 void CopyFrom(const Container& container) const {
294 Clear();
295 MergeFrom(container);
296 }
297
298 private:
299 friend class Reflection;
300 MutableRepeatedFieldRef(
301 Message* message,
302 const FieldDescriptor* field) {
303 const Reflection* reflection = message->GetReflection();
304 data_ = reflection->RepeatedFieldData(
305 message, field, internal::RefTypeTraits<T>::cpp_type,
306 internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
307 accessor_ = reflection->RepeatedFieldAccessor(field);
308 default_instance_ =
309 reflection->GetMessageFactory()->GetPrototype(field->message_type());
310 }
311
312 void* data_;
313 const AccessorType* accessor_;
314 const Message* default_instance_;
315};
316
317namespace internal {
318// Interfaces used to implement reflection RepeatedFieldRef API.
319// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
320// object that implements the below interface.
321//
322// This interface passes/returns values using void pointers. The actual type
323// of the value depends on the field's cpp_type. Following is a mapping from
324// cpp_type to the type that should be used in this interface:
325//
326// field->cpp_type() T Actual type of void*
327// CPPTYPE_INT32 int32 int32
328// CPPTYPE_UINT32 uint32 uint32
329// CPPTYPE_INT64 int64 int64
330// CPPTYPE_UINT64 uint64 uint64
331// CPPTYPE_DOUBLE double double
332// CPPTYPE_FLOAT float float
333// CPPTYPE_BOOL bool bool
334// CPPTYPE_ENUM generated enum type int32
335// CPPTYPE_STRING string string
336// CPPTYPE_MESSAGE generated message type google::protobuf::Message
337// or google::protobuf::Message
338//
339// Note that for enums we use int32 in the interface.
340//
341// You can map from T to the actual type using RefTypeTraits:
342// typedef RefTypeTraits<T>::AccessorValueType ActualType;
343class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
344 public:
345 // Typedefs for clarity.
346 typedef void Field;
347 typedef void Value;
348 typedef void Iterator;
349
350 virtual ~RepeatedFieldAccessor();
351 virtual bool IsEmpty(const Field* data) const = 0;
352 virtual int Size(const Field* data) const = 0;
353 // Depends on the underlying representation of the repeated field, this
354 // method can return a pointer to the underlying object if such an object
355 // exists, or fill the data into scratch_space and return scratch_space.
356 // Callers of this method must ensure scratch_space is a valid pointer
357 // to a mutable object of the correct type.
358 virtual const Value* Get(
359 const Field* data, int index, Value* scratch_space) const = 0;
360
361 virtual void Clear(Field* data) const = 0;
362 virtual void Set(Field* data, int index, const Value* value) const = 0;
363 virtual void Add(Field* data, const Value* value) const = 0;
364 virtual void RemoveLast(Field* data) const = 0;
365 virtual void SwapElements(Field* data, int index1, int index2) const = 0;
366 virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
367 Field* other_data) const = 0;
368
Austin Schuh40c16522018-10-28 20:27:54 -0700369 // Create an iterator that points at the beginning of the repeated field.
Brian Silverman9c614bc2016-02-15 20:20:02 -0500370 virtual Iterator* BeginIterator(const Field* data) const = 0;
371 // Create an iterator that points at the end of the repeated field.
372 virtual Iterator* EndIterator(const Field* data) const = 0;
373 // Make a copy of an iterator and return the new copy.
374 virtual Iterator* CopyIterator(const Field* data,
375 const Iterator* iterator) const = 0;
376 // Move an iterator to point to the next element.
377 virtual Iterator* AdvanceIterator(const Field* data,
378 Iterator* iterator) const = 0;
379 // Compare whether two iterators point to the same element.
380 virtual bool EqualsIterator(const Field* data, const Iterator* a,
381 const Iterator* b) const = 0;
382 // Delete an iterator created by BeginIterator(), EndIterator() and
383 // CopyIterator().
384 virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
385 // Like Get() but for iterators.
386 virtual const Value* GetIteratorValue(const Field* data,
387 const Iterator* iterator,
388 Value* scratch_space) const = 0;
389
390 // Templated methods that make using this interface easier for non-message
391 // types.
392 template<typename T>
393 T Get(const Field* data, int index) const {
394 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
395 ActualType scratch_space;
396 return static_cast<T>(
397 *reinterpret_cast<const ActualType*>(
398 Get(data, index, static_cast<Value*>(&scratch_space))));
399 }
400
401 template<typename T, typename ValueType>
402 void Set(Field* data, int index, const ValueType& value) const {
403 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
404 // In this RepeatedFieldAccessor interface we pass/return data using
405 // raw pointers. Type of the data these raw pointers point to should
406 // be ActualType. Here we have a ValueType object and want a ActualType
407 // pointer. We can't cast a ValueType pointer to an ActualType pointer
408 // directly because their type might be different (for enums ValueType
409 // may be a generated enum type while ActualType is int32). To be safe
410 // we make a copy to get a temporary ActualType object and use it.
411 ActualType tmp = static_cast<ActualType>(value);
412 Set(data, index, static_cast<const Value*>(&tmp));
413 }
414
415 template<typename T, typename ValueType>
416 void Add(Field* data, const ValueType& value) const {
417 typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
418 // In this RepeatedFieldAccessor interface we pass/return data using
419 // raw pointers. Type of the data these raw pointers point to should
420 // be ActualType. Here we have a ValueType object and want a ActualType
421 // pointer. We can't cast a ValueType pointer to an ActualType pointer
422 // directly because their type might be different (for enums ValueType
423 // may be a generated enum type while ActualType is int32). To be safe
424 // we make a copy to get a temporary ActualType object and use it.
425 ActualType tmp = static_cast<ActualType>(value);
426 Add(data, static_cast<const Value*>(&tmp));
427 }
428};
429
430// Implement (Mutable)RepeatedFieldRef::iterator
431template<typename T>
432class RepeatedFieldRefIterator
433 : public std::iterator<std::forward_iterator_tag, T> {
434 typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
435 typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
436 typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
437
438 public:
439 // Constructor for non-message fields.
440 RepeatedFieldRefIterator(const void* data,
Austin Schuh40c16522018-10-28 20:27:54 -0700441 const RepeatedFieldAccessor* accessor, bool begin)
442 : data_(data),
443 accessor_(accessor),
444 iterator_(begin ? accessor->BeginIterator(data)
445 : accessor->EndIterator(data)),
446 // The end iterator must not be dereferenced, no need for scratch space.
447 scratch_space_(begin ? new AccessorValueType : nullptr) {}
Brian Silverman9c614bc2016-02-15 20:20:02 -0500448 // Constructor for message fields.
449 RepeatedFieldRefIterator(const void* data,
450 const RepeatedFieldAccessor* accessor,
451 bool begin,
452 AccessorValueType* scratch_space)
453 : data_(data), accessor_(accessor),
454 iterator_(begin ? accessor->BeginIterator(data) :
455 accessor->EndIterator(data)),
456 scratch_space_(scratch_space) {
457 }
458 ~RepeatedFieldRefIterator() {
459 accessor_->DeleteIterator(data_, iterator_);
460 }
461 RepeatedFieldRefIterator operator++(int) {
462 RepeatedFieldRefIterator tmp(*this);
463 iterator_ = accessor_->AdvanceIterator(data_, iterator_);
464 return tmp;
465 }
466 RepeatedFieldRefIterator& operator++() {
467 iterator_ = accessor_->AdvanceIterator(data_, iterator_);
468 return *this;
469 }
470 IteratorValueType operator*() const {
471 return static_cast<IteratorValueType>(
472 *static_cast<const AccessorValueType*>(
473 accessor_->GetIteratorValue(
474 data_, iterator_, scratch_space_.get())));
475 }
476 IteratorPointerType operator->() const {
477 return static_cast<IteratorPointerType>(
478 accessor_->GetIteratorValue(
479 data_, iterator_, scratch_space_.get()));
480 }
481 bool operator!=(const RepeatedFieldRefIterator& other) const {
482 assert(data_ == other.data_);
483 assert(accessor_ == other.accessor_);
484 return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
485 }
486 bool operator==(const RepeatedFieldRefIterator& other) const {
487 return !this->operator!=(other);
488 }
489
490 RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
491 : data_(other.data_), accessor_(other.accessor_),
492 iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
493 }
494 RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
495 if (this != &other) {
496 accessor_->DeleteIterator(data_, iterator_);
497 data_ = other.data_;
498 accessor_ = other.accessor_;
499 iterator_ = accessor_->CopyIterator(data_, other.iterator_);
500 }
501 return *this;
502 }
503
504 protected:
505 const void* data_;
506 const RepeatedFieldAccessor* accessor_;
507 void* iterator_;
Austin Schuh40c16522018-10-28 20:27:54 -0700508 std::unique_ptr<AccessorValueType> scratch_space_;
Brian Silverman9c614bc2016-02-15 20:20:02 -0500509};
510
511// TypeTraits that maps the type parameter T of RepeatedFieldRef or
512// MutableRepeatedFieldRef to corresponding iterator type,
513// RepeatedFieldAccessor type, etc.
514template<typename T>
515struct PrimitiveTraits {
516 static const bool is_primitive = false;
517};
518#define DEFINE_PRIMITIVE(TYPE, type) \
519 template<> struct PrimitiveTraits<type> { \
520 static const bool is_primitive = true; \
521 static const FieldDescriptor::CppType cpp_type = \
522 FieldDescriptor::CPPTYPE_ ## TYPE; \
523 };
524DEFINE_PRIMITIVE(INT32, int32)
525DEFINE_PRIMITIVE(UINT32, uint32)
526DEFINE_PRIMITIVE(INT64, int64)
527DEFINE_PRIMITIVE(UINT64, uint64)
528DEFINE_PRIMITIVE(FLOAT, float)
529DEFINE_PRIMITIVE(DOUBLE, double)
530DEFINE_PRIMITIVE(BOOL, bool)
531#undef DEFINE_PRIMITIVE
532
533template<typename T>
534struct RefTypeTraits<
Austin Schuh40c16522018-10-28 20:27:54 -0700535 T, typename std::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500536 typedef RepeatedFieldRefIterator<T> iterator;
537 typedef RepeatedFieldAccessor AccessorType;
538 typedef T AccessorValueType;
539 typedef T IteratorValueType;
540 typedef T* IteratorPointerType;
541 static const FieldDescriptor::CppType cpp_type =
542 PrimitiveTraits<T>::cpp_type;
543 static const Descriptor* GetMessageFieldDescriptor() {
544 return NULL;
545 }
546};
547
548template<typename T>
549struct RefTypeTraits<
Austin Schuh40c16522018-10-28 20:27:54 -0700550 T, typename std::enable_if<is_proto_enum<T>::value>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500551 typedef RepeatedFieldRefIterator<T> iterator;
552 typedef RepeatedFieldAccessor AccessorType;
553 // We use int32 for repeated enums in RepeatedFieldAccessor.
554 typedef int32 AccessorValueType;
555 typedef T IteratorValueType;
556 typedef int32* IteratorPointerType;
557 static const FieldDescriptor::CppType cpp_type =
558 FieldDescriptor::CPPTYPE_ENUM;
559 static const Descriptor* GetMessageFieldDescriptor() {
560 return NULL;
561 }
562};
563
564template<typename T>
565struct RefTypeTraits<
Austin Schuh40c16522018-10-28 20:27:54 -0700566 T, typename std::enable_if<std::is_same<string, T>::value>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500567 typedef RepeatedFieldRefIterator<T> iterator;
568 typedef RepeatedFieldAccessor AccessorType;
569 typedef string AccessorValueType;
Austin Schuh40c16522018-10-28 20:27:54 -0700570 typedef const string IteratorValueType;
571 typedef const string* IteratorPointerType;
Brian Silverman9c614bc2016-02-15 20:20:02 -0500572 static const FieldDescriptor::CppType cpp_type =
573 FieldDescriptor::CPPTYPE_STRING;
574 static const Descriptor* GetMessageFieldDescriptor() {
575 return NULL;
576 }
577};
578
579template<typename T>
580struct MessageDescriptorGetter {
581 static const Descriptor* get() {
582 return T::default_instance().GetDescriptor();
583 }
584};
585template<>
586struct MessageDescriptorGetter<Message> {
587 static const Descriptor* get() {
588 return NULL;
589 }
590};
591
592template<typename T>
593struct RefTypeTraits<
Austin Schuh40c16522018-10-28 20:27:54 -0700594 T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500595 typedef RepeatedFieldRefIterator<T> iterator;
596 typedef RepeatedFieldAccessor AccessorType;
597 typedef Message AccessorValueType;
598 typedef const T& IteratorValueType;
599 typedef const T* IteratorPointerType;
600 static const FieldDescriptor::CppType cpp_type =
601 FieldDescriptor::CPPTYPE_MESSAGE;
602 static const Descriptor* GetMessageFieldDescriptor() {
603 return MessageDescriptorGetter<T>::get();
604 }
605};
606} // namespace internal
607} // namespace protobuf
608} // namespace google
609
610#endif // GOOGLE_PROTOBUF_REFLECTION_H__