Home | History | Annotate | Download | only in protobuf
      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>
     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>
     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:
     71   bool empty() const {
     72     return accessor_->IsEmpty(data_);
     73   }
     74   int size() const {
     75     return accessor_->Size(data_);
     76   }
     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;
     83   iterator begin() const {
     84     return iterator(data_, accessor_, true);
     85   }
     86   iterator end() const {
     87     return iterator(data_, accessor_, false);
     88   }
     89 
     90  private:
     91   friend class Reflection;
     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:
    113   bool empty() const {
    114     return accessor_->IsEmpty(data_);
    115   }
    116   int size() const {
    117     return accessor_->Size(data_);
    118   }
    119   T Get(int index) const {
    120     return accessor_->template Get<T>(data_, index);
    121   }
    122 
    123   void Set(int index, const T& value) const {
    124     accessor_->template Set<T>(data_, index, value);
    125   }
    126   void Add(const T& value) const {
    127     accessor_->template Add<T>(data_, value);
    128   }
    129   void RemoveLast() const {
    130     accessor_->RemoveLast(data_);
    131   }
    132   void SwapElements(int index1, int index2) const {
    133     accessor_->SwapElements(data_, index1, index2);
    134   }
    135   void Clear() const {
    136     accessor_->Clear(data_);
    137   }
    138 
    139   void Swap(const MutableRepeatedFieldRef& other) const {
    140     accessor_->Swap(data_, other.accessor_, other.data_);
    141   }
    142 
    143   template<typename 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>
    151   void CopyFrom(const Container& container) const {
    152     Clear();
    153     MergeFrom(container);
    154   }
    155 
    156  private:
    157   friend class Reflection;
    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:
    179   bool empty() const {
    180     return accessor_->IsEmpty(data_);
    181   }
    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());
    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.
    199   T* NewMessage() const {
    200     return static_cast<T*>(default_instance_->New());
    201   }
    202 
    203   typedef IteratorType iterator;
    204   typedef IteratorType const_iterator;
    205   iterator begin() const {
    206     return iterator(data_, accessor_, true, NewMessage());
    207   }
    208   iterator end() const {
    209     return iterator(data_, accessor_, false, NewMessage());
    210   }
    211 
    212  private:
    213   friend class Reflection;
    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:
    239   bool empty() const {
    240     return accessor_->IsEmpty(data_);
    241   }
    242   int size() const {
    243     return accessor_->Size(data_);
    244   }
    245   // See comments for RepeatedFieldRef<Message>::Get()
    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.
    251   T* NewMessage() const {
    252     return static_cast<T*>(default_instance_->New());
    253   }
    254 
    255   void Set(int index, const T& value) const {
    256     accessor_->Set(data_, index, &value);
    257   }
    258   void Add(const T& value) const {
    259     accessor_->Add(data_, &value);
    260   }
    261   void RemoveLast() const {
    262     accessor_->RemoveLast(data_);
    263   }
    264   void SwapElements(int index1, int index2) const {
    265     accessor_->SwapElements(data_, index1, index2);
    266   }
    267   void Clear() const {
    268     accessor_->Clear(data_);
    269   }
    270 
    271   void Swap(const MutableRepeatedFieldRef& other) const {
    272     accessor_->Swap(data_, other.accessor_, other.data_);
    273   }
    274 
    275   template<typename 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>
    283   void CopyFrom(const Container& container) const {
    284     Clear();
    285     MergeFrom(container);
    286   }
    287 
    288  private:
    289   friend class Reflection;
    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>
    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>
    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>
    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.
    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.
    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   }
    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 
    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