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