• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Mappings and Sequences of descriptors.
32 // Used by Descriptor.fields_by_name, EnumDescriptor.values...
33 //
34 // They avoid the allocation of a full dictionary or a full list: they simply
35 // store a pointer to the parent descriptor, use the C++ Descriptor methods (see
36 // google/protobuf/descriptor.h) to retrieve other descriptors, and create
37 // Python objects on the fly.
38 //
39 // The containers fully conform to abc.Mapping and abc.Sequence, and behave just
40 // like read-only dictionaries and lists.
41 //
42 // Because the interface of C++ Descriptors is quite regular, this file actually
43 // defines only three types, the exact behavior of a container is controlled by
44 // a DescriptorContainerDef structure, which contains functions that uses the
45 // public Descriptor API.
46 //
47 // Note: This DescriptorContainerDef is similar to the "virtual methods table"
48 // that a C++ compiler generates for a class. We have to make it explicit
49 // because the Python API is based on C, and does not play well with C++
50 // inheritance.
51 
52 #include <Python.h>
53 
54 #include <google/protobuf/descriptor.h>
55 #include <google/protobuf/pyext/descriptor_containers.h>
56 #include <google/protobuf/pyext/descriptor_pool.h>
57 #include <google/protobuf/pyext/descriptor.h>
58 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
59 
60 #if PY_MAJOR_VERSION >= 3
61   #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
62   #define PyString_FromFormat PyUnicode_FromFormat
63   #define PyInt_FromLong PyLong_FromLong
64   #if PY_VERSION_HEX < 0x03030000
65     #error "Python 3.0 - 3.2 are not supported."
66   #endif
67   #define PyString_AsStringAndSize(ob, charpp, sizep) \
68     (PyUnicode_Check(ob)? \
69        ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
70        PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
71 #endif
72 
73 namespace google {
74 namespace protobuf {
75 namespace python {
76 
77 struct PyContainer;
78 
79 typedef int (*CountMethod)(PyContainer* self);
80 typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
81 typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name);
82 typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self,
83                                                 const string& name);
84 typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
85 typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
86 typedef const string& (*GetItemNameMethod)(const void* descriptor);
87 typedef const string& (*GetItemCamelcaseNameMethod)(const void* descriptor);
88 typedef int (*GetItemNumberMethod)(const void* descriptor);
89 typedef int (*GetItemIndexMethod)(const void* descriptor);
90 
91 struct DescriptorContainerDef {
92   const char* mapping_name;
93   // Returns the number of items in the container.
94   CountMethod count_fn;
95   // Retrieve item by index (usually the order of declaration in the proto file)
96   // Used by sequences, but also iterators. 0 <= index < Count().
97   GetByIndexMethod get_by_index_fn;
98   // Retrieve item by name (usually a call to some 'FindByName' method).
99   // Used by "by_name" mappings.
100   GetByNameMethod get_by_name_fn;
101   // Retrieve item by camelcase name (usually a call to some
102   // 'FindByCamelcaseName' method). Used by "by_camelcase_name" mappings.
103   GetByCamelcaseNameMethod get_by_camelcase_name_fn;
104   // Retrieve item by declared number (field tag, or enum value).
105   // Used by "by_number" mappings.
106   GetByNumberMethod get_by_number_fn;
107   // Converts a item C++ descriptor to a Python object. Returns a new reference.
108   NewObjectFromItemMethod new_object_from_item_fn;
109   // Retrieve the name of an item. Used by iterators on "by_name" mappings.
110   GetItemNameMethod get_item_name_fn;
111   // Retrieve the camelcase name of an item. Used by iterators on
112   // "by_camelcase_name" mappings.
113   GetItemCamelcaseNameMethod get_item_camelcase_name_fn;
114   // Retrieve the number of an item. Used by iterators on "by_number" mappings.
115   GetItemNumberMethod get_item_number_fn;
116   // Retrieve the index of an item for the container type.
117   // Used by "__contains__".
118   // If not set, "x in sequence" will do a linear search.
119   GetItemIndexMethod get_item_index_fn;
120 };
121 
122 struct PyContainer {
123   PyObject_HEAD
124 
125   // The proto2 descriptor this container belongs to the global DescriptorPool.
126   const void* descriptor;
127 
128   // A pointer to a static structure with function pointers that control the
129   // behavior of the container. Very similar to the table of virtual functions
130   // of a C++ class.
131   const DescriptorContainerDef* container_def;
132 
133   // The kind of container: list, or dict by name or value.
134   enum ContainerKind {
135     KIND_SEQUENCE,
136     KIND_BYNAME,
137     KIND_BYCAMELCASENAME,
138     KIND_BYNUMBER,
139   } kind;
140 };
141 
142 struct PyContainerIterator {
143   PyObject_HEAD
144 
145   // The container we are iterating over. Own a reference.
146   PyContainer* container;
147 
148   // The current index in the iterator.
149   int index;
150 
151   // The kind of container: list, or dict by name or value.
152   enum IterKind {
153     KIND_ITERKEY,
154     KIND_ITERVALUE,
155     KIND_ITERITEM,
156     KIND_ITERVALUE_REVERSED,  // For sequences
157   } kind;
158 };
159 
160 namespace descriptor {
161 
162 // Returns the C++ item descriptor for a given Python key.
163 // When the descriptor is found, return true and set *item.
164 // When the descriptor is not found, return true, but set *item to NULL.
165 // On error, returns false with an exception set.
_GetItemByKey(PyContainer * self,PyObject * key,const void ** item)166 static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) {
167   switch (self->kind) {
168     case PyContainer::KIND_BYNAME:
169       {
170         char* name;
171         Py_ssize_t name_size;
172         if (PyString_AsStringAndSize(key, &name, &name_size) < 0) {
173           if (PyErr_ExceptionMatches(PyExc_TypeError)) {
174             // Not a string, cannot be in the container.
175             PyErr_Clear();
176             *item = NULL;
177             return true;
178           }
179           return false;
180         }
181         *item = self->container_def->get_by_name_fn(
182             self, string(name, name_size));
183         return true;
184       }
185     case PyContainer::KIND_BYCAMELCASENAME:
186       {
187         char* camelcase_name;
188         Py_ssize_t name_size;
189         if (PyString_AsStringAndSize(key, &camelcase_name, &name_size) < 0) {
190           if (PyErr_ExceptionMatches(PyExc_TypeError)) {
191             // Not a string, cannot be in the container.
192             PyErr_Clear();
193             *item = NULL;
194             return true;
195           }
196           return false;
197         }
198         *item = self->container_def->get_by_camelcase_name_fn(
199             self, string(camelcase_name, name_size));
200         return true;
201       }
202     case PyContainer::KIND_BYNUMBER:
203       {
204         Py_ssize_t number = PyNumber_AsSsize_t(key, NULL);
205         if (number == -1 && PyErr_Occurred()) {
206           if (PyErr_ExceptionMatches(PyExc_TypeError)) {
207             // Not a number, cannot be in the container.
208             PyErr_Clear();
209             *item = NULL;
210             return true;
211           }
212           return false;
213         }
214         *item = self->container_def->get_by_number_fn(self, number);
215         return true;
216       }
217     default:
218       PyErr_SetNone(PyExc_NotImplementedError);
219       return false;
220   }
221 }
222 
223 // Returns the key of the object at the given index.
224 // Used when iterating over mappings.
_NewKey_ByIndex(PyContainer * self,Py_ssize_t index)225 static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
226   const void* item = self->container_def->get_by_index_fn(self, index);
227   switch (self->kind) {
228     case PyContainer::KIND_BYNAME:
229       {
230         const string& name(self->container_def->get_item_name_fn(item));
231         return PyString_FromStringAndSize(name.c_str(), name.size());
232       }
233     case PyContainer::KIND_BYCAMELCASENAME:
234       {
235         const string& name(
236             self->container_def->get_item_camelcase_name_fn(item));
237         return PyString_FromStringAndSize(name.c_str(), name.size());
238       }
239     case PyContainer::KIND_BYNUMBER:
240       {
241         int value = self->container_def->get_item_number_fn(item);
242         return PyInt_FromLong(value);
243       }
244     default:
245       PyErr_SetNone(PyExc_NotImplementedError);
246       return NULL;
247   }
248 }
249 
250 // Returns the object at the given index.
251 // Also used when iterating over mappings.
_NewObj_ByIndex(PyContainer * self,Py_ssize_t index)252 static PyObject* _NewObj_ByIndex(PyContainer* self, Py_ssize_t index) {
253   return self->container_def->new_object_from_item_fn(
254       self->container_def->get_by_index_fn(self, index));
255 }
256 
Length(PyContainer * self)257 static Py_ssize_t Length(PyContainer* self) {
258   return self->container_def->count_fn(self);
259 }
260 
261 // The DescriptorMapping type.
262 
Subscript(PyContainer * self,PyObject * key)263 static PyObject* Subscript(PyContainer* self, PyObject* key) {
264   const void* item = NULL;
265   if (!_GetItemByKey(self, key, &item)) {
266     return NULL;
267   }
268   if (!item) {
269     PyErr_SetObject(PyExc_KeyError, key);
270     return NULL;
271   }
272   return self->container_def->new_object_from_item_fn(item);
273 }
274 
AssSubscript(PyContainer * self,PyObject * key,PyObject * value)275 static int AssSubscript(PyContainer* self, PyObject* key, PyObject* value) {
276   if (_CalledFromGeneratedFile(0)) {
277     return 0;
278   }
279   PyErr_Format(PyExc_TypeError,
280                "'%.200s' object does not support item assignment",
281                Py_TYPE(self)->tp_name);
282   return -1;
283 }
284 
285 static PyMappingMethods MappingMappingMethods = {
286   (lenfunc)Length,               // mp_length
287   (binaryfunc)Subscript,         // mp_subscript
288   (objobjargproc)AssSubscript,   // mp_ass_subscript
289 };
290 
Contains(PyContainer * self,PyObject * key)291 static int Contains(PyContainer* self, PyObject* key) {
292   const void* item = NULL;
293   if (!_GetItemByKey(self, key, &item)) {
294     return -1;
295   }
296   if (item) {
297     return 1;
298   } else {
299     return 0;
300   }
301 }
302 
ContainerRepr(PyContainer * self)303 static PyObject* ContainerRepr(PyContainer* self) {
304   const char* kind = "";
305   switch (self->kind) {
306     case PyContainer::KIND_SEQUENCE:
307       kind = "sequence";
308       break;
309     case PyContainer::KIND_BYNAME:
310       kind = "mapping by name";
311       break;
312     case PyContainer::KIND_BYCAMELCASENAME:
313       kind = "mapping by camelCase name";
314       break;
315     case PyContainer::KIND_BYNUMBER:
316       kind = "mapping by number";
317       break;
318   }
319   return PyString_FromFormat(
320       "<%s %s>", self->container_def->mapping_name, kind);
321 }
322 
323 extern PyTypeObject DescriptorMapping_Type;
324 extern PyTypeObject DescriptorSequence_Type;
325 
326 // A sequence container can only be equal to another sequence container, or (for
327 // backward compatibility) to a list containing the same items.
328 // Returns 1 if equal, 0 if unequal, -1 on error.
DescriptorSequence_Equal(PyContainer * self,PyObject * other)329 static int DescriptorSequence_Equal(PyContainer* self, PyObject* other) {
330   // Check the identity of C++ pointers.
331   if (PyObject_TypeCheck(other, &DescriptorSequence_Type)) {
332     PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
333     if (self->descriptor == other_container->descriptor &&
334         self->container_def == other_container->container_def &&
335         self->kind == other_container->kind) {
336       return 1;
337     } else {
338       return 0;
339     }
340   }
341 
342   // If other is a list
343   if (PyList_Check(other)) {
344     // return list(self) == other
345     int size = Length(self);
346     if (size != PyList_Size(other)) {
347       return false;
348     }
349     for (int index = 0; index < size; index++) {
350       ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
351       if (value1 == NULL) {
352         return -1;
353       }
354       PyObject* value2 = PyList_GetItem(other, index);
355       if (value2 == NULL) {
356         return -1;
357       }
358       int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
359       if (cmp != 1)  // error or not equal
360           return cmp;
361     }
362     // All items were found and equal
363     return 1;
364   }
365 
366   // Any other object is different.
367   return 0;
368 }
369 
370 // A mapping container can only be equal to another mapping container, or (for
371 // backward compatibility) to a dict containing the same items.
372 // Returns 1 if equal, 0 if unequal, -1 on error.
DescriptorMapping_Equal(PyContainer * self,PyObject * other)373 static int DescriptorMapping_Equal(PyContainer* self, PyObject* other) {
374   // Check the identity of C++ pointers.
375   if (PyObject_TypeCheck(other, &DescriptorMapping_Type)) {
376     PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
377     if (self->descriptor == other_container->descriptor &&
378         self->container_def == other_container->container_def &&
379         self->kind == other_container->kind) {
380       return 1;
381     } else {
382       return 0;
383     }
384   }
385 
386   // If other is a dict
387   if (PyDict_Check(other)) {
388     // equivalent to dict(self.items()) == other
389     int size = Length(self);
390     if (size != PyDict_Size(other)) {
391       return false;
392     }
393     for (int index = 0; index < size; index++) {
394       ScopedPyObjectPtr key(_NewKey_ByIndex(self, index));
395       if (key == NULL) {
396         return -1;
397       }
398       ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
399       if (value1 == NULL) {
400         return -1;
401       }
402       PyObject* value2 = PyDict_GetItem(other, key.get());
403       if (value2 == NULL) {
404         // Not found in the other dictionary
405         return 0;
406       }
407       int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
408       if (cmp != 1)  // error or not equal
409           return cmp;
410     }
411     // All items were found and equal
412     return 1;
413   }
414 
415   // Any other object is different.
416   return 0;
417 }
418 
RichCompare(PyContainer * self,PyObject * other,int opid)419 static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) {
420   if (opid != Py_EQ && opid != Py_NE) {
421     Py_INCREF(Py_NotImplemented);
422     return Py_NotImplemented;
423   }
424 
425   int result;
426 
427   if (self->kind == PyContainer::KIND_SEQUENCE) {
428     result = DescriptorSequence_Equal(self, other);
429   } else {
430     result = DescriptorMapping_Equal(self, other);
431   }
432   if (result < 0) {
433     return NULL;
434   }
435   if (result ^ (opid == Py_NE)) {
436     Py_RETURN_TRUE;
437   } else {
438     Py_RETURN_FALSE;
439   }
440 }
441 
442 static PySequenceMethods MappingSequenceMethods = {
443     0,                      // sq_length
444     0,                      // sq_concat
445     0,                      // sq_repeat
446     0,                      // sq_item
447     0,                      // sq_slice
448     0,                      // sq_ass_item
449     0,                      // sq_ass_slice
450     (objobjproc)Contains,   // sq_contains
451 };
452 
Get(PyContainer * self,PyObject * args)453 static PyObject* Get(PyContainer* self, PyObject* args) {
454   PyObject* key;
455   PyObject* default_value = Py_None;
456   if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
457     return NULL;
458   }
459 
460   const void* item;
461   if (!_GetItemByKey(self, key, &item)) {
462     return NULL;
463   }
464   if (item == NULL) {
465     Py_INCREF(default_value);
466     return default_value;
467   }
468   return self->container_def->new_object_from_item_fn(item);
469 }
470 
Keys(PyContainer * self,PyObject * args)471 static PyObject* Keys(PyContainer* self, PyObject* args) {
472   Py_ssize_t count = Length(self);
473   ScopedPyObjectPtr list(PyList_New(count));
474   if (list == NULL) {
475     return NULL;
476   }
477   for (Py_ssize_t index = 0; index < count; ++index) {
478     PyObject* key = _NewKey_ByIndex(self, index);
479     if (key == NULL) {
480       return NULL;
481     }
482     PyList_SET_ITEM(list.get(), index, key);
483   }
484   return list.release();
485 }
486 
Values(PyContainer * self,PyObject * args)487 static PyObject* Values(PyContainer* self, PyObject* args) {
488   Py_ssize_t count = Length(self);
489   ScopedPyObjectPtr list(PyList_New(count));
490   if (list == NULL) {
491     return NULL;
492   }
493   for (Py_ssize_t index = 0; index < count; ++index) {
494     PyObject* value = _NewObj_ByIndex(self, index);
495     if (value == NULL) {
496       return NULL;
497     }
498     PyList_SET_ITEM(list.get(), index, value);
499   }
500   return list.release();
501 }
502 
Items(PyContainer * self,PyObject * args)503 static PyObject* Items(PyContainer* self, PyObject* args) {
504   Py_ssize_t count = Length(self);
505   ScopedPyObjectPtr list(PyList_New(count));
506   if (list == NULL) {
507     return NULL;
508   }
509   for (Py_ssize_t index = 0; index < count; ++index) {
510     ScopedPyObjectPtr obj(PyTuple_New(2));
511     if (obj == NULL) {
512       return NULL;
513     }
514     PyObject* key = _NewKey_ByIndex(self, index);
515     if (key == NULL) {
516       return NULL;
517     }
518     PyTuple_SET_ITEM(obj.get(), 0, key);
519     PyObject* value = _NewObj_ByIndex(self, index);
520     if (value == NULL) {
521       return NULL;
522     }
523     PyTuple_SET_ITEM(obj.get(), 1, value);
524     PyList_SET_ITEM(list.get(), index, obj.release());
525   }
526   return list.release();
527 }
528 
529 static PyObject* NewContainerIterator(PyContainer* mapping,
530                                       PyContainerIterator::IterKind kind);
531 
Iter(PyContainer * self)532 static PyObject* Iter(PyContainer* self) {
533   return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
534 }
IterKeys(PyContainer * self,PyObject * args)535 static PyObject* IterKeys(PyContainer* self, PyObject* args) {
536   return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
537 }
IterValues(PyContainer * self,PyObject * args)538 static PyObject* IterValues(PyContainer* self, PyObject* args) {
539   return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE);
540 }
IterItems(PyContainer * self,PyObject * args)541 static PyObject* IterItems(PyContainer* self, PyObject* args) {
542   return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM);
543 }
544 
545 static PyMethodDef MappingMethods[] = {
546   { "get", (PyCFunction)Get, METH_VARARGS, },
547   { "keys", (PyCFunction)Keys, METH_NOARGS, },
548   { "values", (PyCFunction)Values, METH_NOARGS, },
549   { "items", (PyCFunction)Items, METH_NOARGS, },
550   { "iterkeys", (PyCFunction)IterKeys, METH_NOARGS, },
551   { "itervalues", (PyCFunction)IterValues, METH_NOARGS, },
552   { "iteritems", (PyCFunction)IterItems, METH_NOARGS, },
553   {NULL}
554 };
555 
556 PyTypeObject DescriptorMapping_Type = {
557   PyVarObject_HEAD_INIT(&PyType_Type, 0)
558   "DescriptorMapping",                  // tp_name
559   sizeof(PyContainer),                  // tp_basicsize
560   0,                                    // tp_itemsize
561   0,                                    // tp_dealloc
562   0,                                    // tp_print
563   0,                                    // tp_getattr
564   0,                                    // tp_setattr
565   0,                                    // tp_compare
566   (reprfunc)ContainerRepr,              // tp_repr
567   0,                                    // tp_as_number
568   &MappingSequenceMethods,              // tp_as_sequence
569   &MappingMappingMethods,               // tp_as_mapping
570   0,                                    // tp_hash
571   0,                                    // tp_call
572   0,                                    // tp_str
573   0,                                    // tp_getattro
574   0,                                    // tp_setattro
575   0,                                    // tp_as_buffer
576   Py_TPFLAGS_DEFAULT,                   // tp_flags
577   0,                                    // tp_doc
578   0,                                    // tp_traverse
579   0,                                    // tp_clear
580   (richcmpfunc)RichCompare,             // tp_richcompare
581   0,                                    // tp_weaklistoffset
582   (getiterfunc)Iter,                    // tp_iter
583   0,                                    // tp_iternext
584   MappingMethods,                       // tp_methods
585   0,                                    // tp_members
586   0,                                    // tp_getset
587   0,                                    // tp_base
588   0,                                    // tp_dict
589   0,                                    // tp_descr_get
590   0,                                    // tp_descr_set
591   0,                                    // tp_dictoffset
592   0,                                    // tp_init
593   0,                                    // tp_alloc
594   0,                                    // tp_new
595   0,                                    // tp_free
596 };
597 
598 // The DescriptorSequence type.
599 
GetItem(PyContainer * self,Py_ssize_t index)600 static PyObject* GetItem(PyContainer* self, Py_ssize_t index) {
601   if (index < 0) {
602     index += Length(self);
603   }
604   if (index < 0 || index >= Length(self)) {
605     PyErr_SetString(PyExc_IndexError, "index out of range");
606     return NULL;
607   }
608   return _NewObj_ByIndex(self, index);
609 }
610 
611 static PyObject *
SeqSubscript(PyContainer * self,PyObject * item)612 SeqSubscript(PyContainer* self, PyObject* item) {
613   if (PyIndex_Check(item)) {
614       Py_ssize_t index;
615       index = PyNumber_AsSsize_t(item, PyExc_IndexError);
616       if (index == -1 && PyErr_Occurred())
617           return NULL;
618       return GetItem(self, index);
619   }
620   // Materialize the list and delegate the operation to it.
621   ScopedPyObjectPtr list(PyObject_CallFunctionObjArgs(
622       reinterpret_cast<PyObject*>(&PyList_Type), self, NULL));
623   if (list == NULL) {
624     return NULL;
625   }
626   return Py_TYPE(list.get())->tp_as_mapping->mp_subscript(list.get(), item);
627 }
628 
629 // Returns the position of the item in the sequence, of -1 if not found.
630 // This function never fails.
Find(PyContainer * self,PyObject * item)631 int Find(PyContainer* self, PyObject* item) {
632   // The item can only be in one position: item.index.
633   // Check that self[item.index] == item, it's faster than a linear search.
634   //
635   // This assumes that sequences are only defined by syntax of the .proto file:
636   // a specific item belongs to only one sequence, depending on its position in
637   // the .proto file definition.
638   const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item);
639   if (descriptor_ptr == NULL) {
640     // Not a descriptor, it cannot be in the list.
641     return -1;
642   }
643   if (self->container_def->get_item_index_fn) {
644     int index = self->container_def->get_item_index_fn(descriptor_ptr);
645     if (index < 0 || index >= Length(self)) {
646       // This index is not from this collection.
647       return -1;
648     }
649     if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) {
650       // The descriptor at this index is not the same.
651       return -1;
652     }
653     // self[item.index] == item, so return the index.
654     return index;
655   } else {
656     // Fall back to linear search.
657     int length = Length(self);
658     for (int index=0; index < length; index++) {
659       if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) {
660         return index;
661       }
662     }
663     // Not found
664     return -1;
665   }
666 }
667 
668 // Implements list.index(): the position of the item is in the sequence.
Index(PyContainer * self,PyObject * item)669 static PyObject* Index(PyContainer* self, PyObject* item) {
670   int position = Find(self, item);
671   if (position < 0) {
672     // Not found
673     PyErr_SetNone(PyExc_ValueError);
674     return NULL;
675   } else {
676     return PyInt_FromLong(position);
677   }
678 }
679 // Implements "list.__contains__()": is the object in the sequence.
SeqContains(PyContainer * self,PyObject * item)680 static int SeqContains(PyContainer* self, PyObject* item) {
681   int position = Find(self, item);
682   if (position < 0) {
683     return 0;
684   } else {
685     return 1;
686   }
687 }
688 
689 // Implements list.count(): number of occurrences of the item in the sequence.
690 // An item can only appear once in a sequence. If it exists, return 1.
Count(PyContainer * self,PyObject * item)691 static PyObject* Count(PyContainer* self, PyObject* item) {
692   int position = Find(self, item);
693   if (position < 0) {
694     return PyInt_FromLong(0);
695   } else {
696     return PyInt_FromLong(1);
697   }
698 }
699 
Append(PyContainer * self,PyObject * args)700 static PyObject* Append(PyContainer* self, PyObject* args) {
701   if (_CalledFromGeneratedFile(0)) {
702     Py_RETURN_NONE;
703   }
704   PyErr_Format(PyExc_TypeError,
705                "'%.200s' object is not a mutable sequence",
706                Py_TYPE(self)->tp_name);
707   return NULL;
708 }
709 
Reversed(PyContainer * self,PyObject * args)710 static PyObject* Reversed(PyContainer* self, PyObject* args) {
711   return NewContainerIterator(self,
712                               PyContainerIterator::KIND_ITERVALUE_REVERSED);
713 }
714 
715 static PyMethodDef SeqMethods[] = {
716   { "index", (PyCFunction)Index, METH_O, },
717   { "count", (PyCFunction)Count, METH_O, },
718   { "append", (PyCFunction)Append, METH_O, },
719   { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
720   {NULL}
721 };
722 
723 static PySequenceMethods SeqSequenceMethods = {
724   (lenfunc)Length,          // sq_length
725   0,                        // sq_concat
726   0,                        // sq_repeat
727   (ssizeargfunc)GetItem,    // sq_item
728   0,                        // sq_slice
729   0,                        // sq_ass_item
730   0,                        // sq_ass_slice
731   (objobjproc)SeqContains,  // sq_contains
732 };
733 
734 static PyMappingMethods SeqMappingMethods = {
735   (lenfunc)Length,           // mp_length
736   (binaryfunc)SeqSubscript,  // mp_subscript
737   0,                         // mp_ass_subscript
738 };
739 
740 PyTypeObject DescriptorSequence_Type = {
741   PyVarObject_HEAD_INIT(&PyType_Type, 0)
742   "DescriptorSequence",                 // tp_name
743   sizeof(PyContainer),                  // tp_basicsize
744   0,                                    // tp_itemsize
745   0,                                    // tp_dealloc
746   0,                                    // tp_print
747   0,                                    // tp_getattr
748   0,                                    // tp_setattr
749   0,                                    // tp_compare
750   (reprfunc)ContainerRepr,              // tp_repr
751   0,                                    // tp_as_number
752   &SeqSequenceMethods,                  // tp_as_sequence
753   &SeqMappingMethods,                   // tp_as_mapping
754   0,                                    // tp_hash
755   0,                                    // tp_call
756   0,                                    // tp_str
757   0,                                    // tp_getattro
758   0,                                    // tp_setattro
759   0,                                    // tp_as_buffer
760   Py_TPFLAGS_DEFAULT,                   // tp_flags
761   0,                                    // tp_doc
762   0,                                    // tp_traverse
763   0,                                    // tp_clear
764   (richcmpfunc)RichCompare,             // tp_richcompare
765   0,                                    // tp_weaklistoffset
766   0,                                    // tp_iter
767   0,                                    // tp_iternext
768   SeqMethods,                           // tp_methods
769   0,                                    // tp_members
770   0,                                    // tp_getset
771   0,                                    // tp_base
772   0,                                    // tp_dict
773   0,                                    // tp_descr_get
774   0,                                    // tp_descr_set
775   0,                                    // tp_dictoffset
776   0,                                    // tp_init
777   0,                                    // tp_alloc
778   0,                                    // tp_new
779   0,                                    // tp_free
780 };
781 
NewMappingByName(DescriptorContainerDef * container_def,const void * descriptor)782 static PyObject* NewMappingByName(
783     DescriptorContainerDef* container_def, const void* descriptor) {
784   PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
785   if (self == NULL) {
786     return NULL;
787   }
788   self->descriptor = descriptor;
789   self->container_def = container_def;
790   self->kind = PyContainer::KIND_BYNAME;
791   return reinterpret_cast<PyObject*>(self);
792 }
793 
NewMappingByCamelcaseName(DescriptorContainerDef * container_def,const void * descriptor)794 static PyObject* NewMappingByCamelcaseName(
795     DescriptorContainerDef* container_def, const void* descriptor) {
796   PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
797   if (self == NULL) {
798     return NULL;
799   }
800   self->descriptor = descriptor;
801   self->container_def = container_def;
802   self->kind = PyContainer::KIND_BYCAMELCASENAME;
803   return reinterpret_cast<PyObject*>(self);
804 }
805 
NewMappingByNumber(DescriptorContainerDef * container_def,const void * descriptor)806 static PyObject* NewMappingByNumber(
807     DescriptorContainerDef* container_def, const void* descriptor) {
808   if (container_def->get_by_number_fn == NULL ||
809       container_def->get_item_number_fn == NULL) {
810     PyErr_SetNone(PyExc_NotImplementedError);
811     return NULL;
812   }
813   PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
814   if (self == NULL) {
815     return NULL;
816   }
817   self->descriptor = descriptor;
818   self->container_def = container_def;
819   self->kind = PyContainer::KIND_BYNUMBER;
820   return reinterpret_cast<PyObject*>(self);
821 }
822 
NewSequence(DescriptorContainerDef * container_def,const void * descriptor)823 static PyObject* NewSequence(
824     DescriptorContainerDef* container_def, const void* descriptor) {
825   PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type);
826   if (self == NULL) {
827     return NULL;
828   }
829   self->descriptor = descriptor;
830   self->container_def = container_def;
831   self->kind = PyContainer::KIND_SEQUENCE;
832   return reinterpret_cast<PyObject*>(self);
833 }
834 
835 // Implement iterators over PyContainers.
836 
Iterator_Dealloc(PyContainerIterator * self)837 static void Iterator_Dealloc(PyContainerIterator* self) {
838   Py_CLEAR(self->container);
839   Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
840 }
841 
Iterator_Next(PyContainerIterator * self)842 static PyObject* Iterator_Next(PyContainerIterator* self) {
843   int count = self->container->container_def->count_fn(self->container);
844   if (self->index >= count) {
845     // Return NULL with no exception to indicate the end.
846     return NULL;
847   }
848   int index = self->index;
849   self->index += 1;
850   switch (self->kind) {
851     case PyContainerIterator::KIND_ITERKEY:
852       return _NewKey_ByIndex(self->container, index);
853     case PyContainerIterator::KIND_ITERVALUE:
854       return _NewObj_ByIndex(self->container, index);
855     case PyContainerIterator::KIND_ITERVALUE_REVERSED:
856       return _NewObj_ByIndex(self->container, count - index - 1);
857     case PyContainerIterator::KIND_ITERITEM:
858       {
859         PyObject* obj = PyTuple_New(2);
860         if (obj == NULL) {
861           return NULL;
862         }
863         PyObject* key = _NewKey_ByIndex(self->container, index);
864         if (key == NULL) {
865           Py_DECREF(obj);
866           return NULL;
867         }
868         PyTuple_SET_ITEM(obj, 0, key);
869         PyObject* value = _NewObj_ByIndex(self->container, index);
870         if (value == NULL) {
871           Py_DECREF(obj);
872           return NULL;
873         }
874         PyTuple_SET_ITEM(obj, 1, value);
875         return obj;
876       }
877     default:
878       PyErr_SetNone(PyExc_NotImplementedError);
879       return NULL;
880   }
881 }
882 
883 static PyTypeObject ContainerIterator_Type = {
884   PyVarObject_HEAD_INIT(&PyType_Type, 0)
885   "DescriptorContainerIterator",        // tp_name
886   sizeof(PyContainerIterator),          // tp_basicsize
887   0,                                    // tp_itemsize
888   (destructor)Iterator_Dealloc,         // tp_dealloc
889   0,                                    // tp_print
890   0,                                    // tp_getattr
891   0,                                    // tp_setattr
892   0,                                    // tp_compare
893   0,                                    // tp_repr
894   0,                                    // tp_as_number
895   0,                                    // tp_as_sequence
896   0,                                    // tp_as_mapping
897   0,                                    // tp_hash
898   0,                                    // tp_call
899   0,                                    // tp_str
900   0,                                    // tp_getattro
901   0,                                    // tp_setattro
902   0,                                    // tp_as_buffer
903   Py_TPFLAGS_DEFAULT,                   // tp_flags
904   0,                                    // tp_doc
905   0,                                    // tp_traverse
906   0,                                    // tp_clear
907   0,                                    // tp_richcompare
908   0,                                    // tp_weaklistoffset
909   PyObject_SelfIter,                    // tp_iter
910   (iternextfunc)Iterator_Next,          // tp_iternext
911   0,                                    // tp_methods
912   0,                                    // tp_members
913   0,                                    // tp_getset
914   0,                                    // tp_base
915   0,                                    // tp_dict
916   0,                                    // tp_descr_get
917   0,                                    // tp_descr_set
918   0,                                    // tp_dictoffset
919   0,                                    // tp_init
920   0,                                    // tp_alloc
921   0,                                    // tp_new
922   0,                                    // tp_free
923 };
924 
NewContainerIterator(PyContainer * container,PyContainerIterator::IterKind kind)925 static PyObject* NewContainerIterator(PyContainer* container,
926                                       PyContainerIterator::IterKind kind) {
927   PyContainerIterator* self = PyObject_New(PyContainerIterator,
928                                            &ContainerIterator_Type);
929   if (self == NULL) {
930     return NULL;
931   }
932   Py_INCREF(container);
933   self->container = container;
934   self->kind = kind;
935   self->index = 0;
936 
937   return reinterpret_cast<PyObject*>(self);
938 }
939 
940 }  // namespace descriptor
941 
942 // Now define the real collections!
943 
944 namespace message_descriptor {
945 
946 typedef const Descriptor* ParentDescriptor;
947 
GetDescriptor(PyContainer * self)948 static ParentDescriptor GetDescriptor(PyContainer* self) {
949   return reinterpret_cast<ParentDescriptor>(self->descriptor);
950 }
951 
952 namespace fields {
953 
954 typedef const FieldDescriptor* ItemDescriptor;
955 
Count(PyContainer * self)956 static int Count(PyContainer* self) {
957   return GetDescriptor(self)->field_count();
958 }
959 
GetByName(PyContainer * self,const string & name)960 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
961   return GetDescriptor(self)->FindFieldByName(name);
962 }
963 
GetByCamelcaseName(PyContainer * self,const string & name)964 static ItemDescriptor GetByCamelcaseName(PyContainer* self,
965                                          const string& name) {
966   return GetDescriptor(self)->FindFieldByCamelcaseName(name);
967 }
968 
GetByNumber(PyContainer * self,int number)969 static ItemDescriptor GetByNumber(PyContainer* self, int number) {
970   return GetDescriptor(self)->FindFieldByNumber(number);
971 }
972 
GetByIndex(PyContainer * self,int index)973 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
974   return GetDescriptor(self)->field(index);
975 }
976 
NewObjectFromItem(ItemDescriptor item)977 static PyObject* NewObjectFromItem(ItemDescriptor item) {
978   return PyFieldDescriptor_FromDescriptor(item);
979 }
980 
GetItemName(ItemDescriptor item)981 static const string& GetItemName(ItemDescriptor item) {
982   return item->name();
983 }
984 
GetItemCamelcaseName(ItemDescriptor item)985 static const string& GetItemCamelcaseName(ItemDescriptor item) {
986   return item->camelcase_name();
987 }
988 
GetItemNumber(ItemDescriptor item)989 static int GetItemNumber(ItemDescriptor item) {
990   return item->number();
991 }
992 
GetItemIndex(ItemDescriptor item)993 static int GetItemIndex(ItemDescriptor item) {
994   return item->index();
995 }
996 
997 static DescriptorContainerDef ContainerDef = {
998   "MessageFields",
999   (CountMethod)Count,
1000   (GetByIndexMethod)GetByIndex,
1001   (GetByNameMethod)GetByName,
1002   (GetByCamelcaseNameMethod)GetByCamelcaseName,
1003   (GetByNumberMethod)GetByNumber,
1004   (NewObjectFromItemMethod)NewObjectFromItem,
1005   (GetItemNameMethod)GetItemName,
1006   (GetItemCamelcaseNameMethod)GetItemCamelcaseName,
1007   (GetItemNumberMethod)GetItemNumber,
1008   (GetItemIndexMethod)GetItemIndex,
1009 };
1010 
1011 }  // namespace fields
1012 
NewMessageFieldsByName(ParentDescriptor descriptor)1013 PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) {
1014   return descriptor::NewMappingByName(&fields::ContainerDef, descriptor);
1015 }
1016 
NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor)1017 PyObject* NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor) {
1018   return descriptor::NewMappingByCamelcaseName(&fields::ContainerDef,
1019                                                descriptor);
1020 }
1021 
NewMessageFieldsByNumber(ParentDescriptor descriptor)1022 PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) {
1023   return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor);
1024 }
1025 
NewMessageFieldsSeq(ParentDescriptor descriptor)1026 PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) {
1027   return descriptor::NewSequence(&fields::ContainerDef, descriptor);
1028 }
1029 
1030 namespace nested_types {
1031 
1032 typedef const Descriptor* ItemDescriptor;
1033 
Count(PyContainer * self)1034 static int Count(PyContainer* self) {
1035   return GetDescriptor(self)->nested_type_count();
1036 }
1037 
GetByName(PyContainer * self,const string & name)1038 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1039   return GetDescriptor(self)->FindNestedTypeByName(name);
1040 }
1041 
GetByIndex(PyContainer * self,int index)1042 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1043   return GetDescriptor(self)->nested_type(index);
1044 }
1045 
NewObjectFromItem(ItemDescriptor item)1046 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1047   return PyMessageDescriptor_FromDescriptor(item);
1048 }
1049 
GetItemName(ItemDescriptor item)1050 static const string& GetItemName(ItemDescriptor item) {
1051   return item->name();
1052 }
1053 
GetItemIndex(ItemDescriptor item)1054 static int GetItemIndex(ItemDescriptor item) {
1055   return item->index();
1056 }
1057 
1058 static DescriptorContainerDef ContainerDef = {
1059   "MessageNestedTypes",
1060   (CountMethod)Count,
1061   (GetByIndexMethod)GetByIndex,
1062   (GetByNameMethod)GetByName,
1063   (GetByCamelcaseNameMethod)NULL,
1064   (GetByNumberMethod)NULL,
1065   (NewObjectFromItemMethod)NewObjectFromItem,
1066   (GetItemNameMethod)GetItemName,
1067   (GetItemCamelcaseNameMethod)NULL,
1068   (GetItemNumberMethod)NULL,
1069   (GetItemIndexMethod)GetItemIndex,
1070 };
1071 
1072 }  // namespace nested_types
1073 
NewMessageNestedTypesSeq(ParentDescriptor descriptor)1074 PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) {
1075   return descriptor::NewSequence(&nested_types::ContainerDef, descriptor);
1076 }
1077 
NewMessageNestedTypesByName(ParentDescriptor descriptor)1078 PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) {
1079   return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor);
1080 }
1081 
1082 namespace enums {
1083 
1084 typedef const EnumDescriptor* ItemDescriptor;
1085 
Count(PyContainer * self)1086 static int Count(PyContainer* self) {
1087   return GetDescriptor(self)->enum_type_count();
1088 }
1089 
GetByName(PyContainer * self,const string & name)1090 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1091   return GetDescriptor(self)->FindEnumTypeByName(name);
1092 }
1093 
GetByIndex(PyContainer * self,int index)1094 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1095   return GetDescriptor(self)->enum_type(index);
1096 }
1097 
NewObjectFromItem(ItemDescriptor item)1098 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1099   return PyEnumDescriptor_FromDescriptor(item);
1100 }
1101 
GetItemName(ItemDescriptor item)1102 static const string& GetItemName(ItemDescriptor item) {
1103   return item->name();
1104 }
1105 
GetItemIndex(ItemDescriptor item)1106 static int GetItemIndex(ItemDescriptor item) {
1107   return item->index();
1108 }
1109 
1110 static DescriptorContainerDef ContainerDef = {
1111   "MessageNestedEnums",
1112   (CountMethod)Count,
1113   (GetByIndexMethod)GetByIndex,
1114   (GetByNameMethod)GetByName,
1115   (GetByCamelcaseNameMethod)NULL,
1116   (GetByNumberMethod)NULL,
1117   (NewObjectFromItemMethod)NewObjectFromItem,
1118   (GetItemNameMethod)GetItemName,
1119   (GetItemCamelcaseNameMethod)NULL,
1120   (GetItemNumberMethod)NULL,
1121   (GetItemIndexMethod)GetItemIndex,
1122 };
1123 
1124 }  // namespace enums
1125 
NewMessageEnumsByName(ParentDescriptor descriptor)1126 PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) {
1127   return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
1128 }
1129 
NewMessageEnumsSeq(ParentDescriptor descriptor)1130 PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) {
1131   return descriptor::NewSequence(&enums::ContainerDef, descriptor);
1132 }
1133 
1134 namespace enumvalues {
1135 
1136 // This is the "enum_values_by_name" mapping, which collects values from all
1137 // enum types in a message.
1138 //
1139 // Note that the behavior of the C++ descriptor is different: it will search and
1140 // return the first value that matches the name, whereas the Python
1141 // implementation retrieves the last one.
1142 
1143 typedef const EnumValueDescriptor* ItemDescriptor;
1144 
Count(PyContainer * self)1145 static int Count(PyContainer* self) {
1146   int count = 0;
1147   for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) {
1148     count += GetDescriptor(self)->enum_type(i)->value_count();
1149   }
1150   return count;
1151 }
1152 
GetByName(PyContainer * self,const string & name)1153 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1154   return GetDescriptor(self)->FindEnumValueByName(name);
1155 }
1156 
GetByIndex(PyContainer * self,int index)1157 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1158   // This is not optimal, but the number of enums *types* in a given message
1159   // is small.  This function is only used when iterating over the mapping.
1160   const EnumDescriptor* enum_type = NULL;
1161   int enum_type_count = GetDescriptor(self)->enum_type_count();
1162   for (int i = 0; i < enum_type_count; ++i) {
1163     enum_type = GetDescriptor(self)->enum_type(i);
1164     int enum_value_count = enum_type->value_count();
1165     if (index < enum_value_count) {
1166       // Found it!
1167       break;
1168     }
1169     index -= enum_value_count;
1170   }
1171   // The next statement cannot overflow, because this function is only called by
1172   // internal iterators which ensure that 0 <= index < Count().
1173   return enum_type->value(index);
1174 }
1175 
NewObjectFromItem(ItemDescriptor item)1176 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1177   return PyEnumValueDescriptor_FromDescriptor(item);
1178 }
1179 
GetItemName(ItemDescriptor item)1180 static const string& GetItemName(ItemDescriptor item) {
1181   return item->name();
1182 }
1183 
1184 static DescriptorContainerDef ContainerDef = {
1185   "MessageEnumValues",
1186   (CountMethod)Count,
1187   (GetByIndexMethod)GetByIndex,
1188   (GetByNameMethod)GetByName,
1189   (GetByCamelcaseNameMethod)NULL,
1190   (GetByNumberMethod)NULL,
1191   (NewObjectFromItemMethod)NewObjectFromItem,
1192   (GetItemNameMethod)GetItemName,
1193   (GetItemCamelcaseNameMethod)NULL,
1194   (GetItemNumberMethod)NULL,
1195   (GetItemIndexMethod)NULL,
1196 };
1197 
1198 }  // namespace enumvalues
1199 
NewMessageEnumValuesByName(ParentDescriptor descriptor)1200 PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) {
1201   return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
1202 }
1203 
1204 namespace extensions {
1205 
1206 typedef const FieldDescriptor* ItemDescriptor;
1207 
Count(PyContainer * self)1208 static int Count(PyContainer* self) {
1209   return GetDescriptor(self)->extension_count();
1210 }
1211 
GetByName(PyContainer * self,const string & name)1212 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1213   return GetDescriptor(self)->FindExtensionByName(name);
1214 }
1215 
GetByIndex(PyContainer * self,int index)1216 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1217   return GetDescriptor(self)->extension(index);
1218 }
1219 
NewObjectFromItem(ItemDescriptor item)1220 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1221   return PyFieldDescriptor_FromDescriptor(item);
1222 }
1223 
GetItemName(ItemDescriptor item)1224 static const string& GetItemName(ItemDescriptor item) {
1225   return item->name();
1226 }
1227 
GetItemIndex(ItemDescriptor item)1228 static int GetItemIndex(ItemDescriptor item) {
1229   return item->index();
1230 }
1231 
1232 static DescriptorContainerDef ContainerDef = {
1233   "MessageExtensions",
1234   (CountMethod)Count,
1235   (GetByIndexMethod)GetByIndex,
1236   (GetByNameMethod)GetByName,
1237   (GetByCamelcaseNameMethod)NULL,
1238   (GetByNumberMethod)NULL,
1239   (NewObjectFromItemMethod)NewObjectFromItem,
1240   (GetItemNameMethod)GetItemName,
1241   (GetItemCamelcaseNameMethod)NULL,
1242   (GetItemNumberMethod)NULL,
1243   (GetItemIndexMethod)GetItemIndex,
1244 };
1245 
1246 }  // namespace extensions
1247 
NewMessageExtensionsByName(ParentDescriptor descriptor)1248 PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) {
1249   return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
1250 }
1251 
NewMessageExtensionsSeq(ParentDescriptor descriptor)1252 PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) {
1253   return descriptor::NewSequence(&extensions::ContainerDef, descriptor);
1254 }
1255 
1256 namespace oneofs {
1257 
1258 typedef const OneofDescriptor* ItemDescriptor;
1259 
Count(PyContainer * self)1260 static int Count(PyContainer* self) {
1261   return GetDescriptor(self)->oneof_decl_count();
1262 }
1263 
GetByName(PyContainer * self,const string & name)1264 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1265   return GetDescriptor(self)->FindOneofByName(name);
1266 }
1267 
GetByIndex(PyContainer * self,int index)1268 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1269   return GetDescriptor(self)->oneof_decl(index);
1270 }
1271 
NewObjectFromItem(ItemDescriptor item)1272 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1273   return PyOneofDescriptor_FromDescriptor(item);
1274 }
1275 
GetItemName(ItemDescriptor item)1276 static const string& GetItemName(ItemDescriptor item) {
1277   return item->name();
1278 }
1279 
GetItemIndex(ItemDescriptor item)1280 static int GetItemIndex(ItemDescriptor item) {
1281   return item->index();
1282 }
1283 
1284 static DescriptorContainerDef ContainerDef = {
1285   "MessageOneofs",
1286   (CountMethod)Count,
1287   (GetByIndexMethod)GetByIndex,
1288   (GetByNameMethod)GetByName,
1289   (GetByCamelcaseNameMethod)NULL,
1290   (GetByNumberMethod)NULL,
1291   (NewObjectFromItemMethod)NewObjectFromItem,
1292   (GetItemNameMethod)GetItemName,
1293   (GetItemCamelcaseNameMethod)NULL,
1294   (GetItemNumberMethod)NULL,
1295   (GetItemIndexMethod)GetItemIndex,
1296 };
1297 
1298 }  // namespace oneofs
1299 
NewMessageOneofsByName(ParentDescriptor descriptor)1300 PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) {
1301   return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor);
1302 }
1303 
NewMessageOneofsSeq(ParentDescriptor descriptor)1304 PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) {
1305   return descriptor::NewSequence(&oneofs::ContainerDef, descriptor);
1306 }
1307 
1308 }  // namespace message_descriptor
1309 
1310 namespace enum_descriptor {
1311 
1312 typedef const EnumDescriptor* ParentDescriptor;
1313 
GetDescriptor(PyContainer * self)1314 static ParentDescriptor GetDescriptor(PyContainer* self) {
1315   return reinterpret_cast<ParentDescriptor>(self->descriptor);
1316 }
1317 
1318 namespace enumvalues {
1319 
1320 typedef const EnumValueDescriptor* ItemDescriptor;
1321 
Count(PyContainer * self)1322 static int Count(PyContainer* self) {
1323   return GetDescriptor(self)->value_count();
1324 }
1325 
GetByIndex(PyContainer * self,int index)1326 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1327   return GetDescriptor(self)->value(index);
1328 }
1329 
GetByName(PyContainer * self,const string & name)1330 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1331   return GetDescriptor(self)->FindValueByName(name);
1332 }
1333 
GetByNumber(PyContainer * self,int number)1334 static ItemDescriptor GetByNumber(PyContainer* self, int number) {
1335   return GetDescriptor(self)->FindValueByNumber(number);
1336 }
1337 
NewObjectFromItem(ItemDescriptor item)1338 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1339   return PyEnumValueDescriptor_FromDescriptor(item);
1340 }
1341 
GetItemName(ItemDescriptor item)1342 static const string& GetItemName(ItemDescriptor item) {
1343   return item->name();
1344 }
1345 
GetItemNumber(ItemDescriptor item)1346 static int GetItemNumber(ItemDescriptor item) {
1347   return item->number();
1348 }
1349 
GetItemIndex(ItemDescriptor item)1350 static int GetItemIndex(ItemDescriptor item) {
1351   return item->index();
1352 }
1353 
1354 static DescriptorContainerDef ContainerDef = {
1355   "EnumValues",
1356   (CountMethod)Count,
1357   (GetByIndexMethod)GetByIndex,
1358   (GetByNameMethod)GetByName,
1359   (GetByCamelcaseNameMethod)NULL,
1360   (GetByNumberMethod)GetByNumber,
1361   (NewObjectFromItemMethod)NewObjectFromItem,
1362   (GetItemNameMethod)GetItemName,
1363   (GetItemCamelcaseNameMethod)NULL,
1364   (GetItemNumberMethod)GetItemNumber,
1365   (GetItemIndexMethod)GetItemIndex,
1366 };
1367 
1368 }  // namespace enumvalues
1369 
NewEnumValuesByName(ParentDescriptor descriptor)1370 PyObject* NewEnumValuesByName(ParentDescriptor descriptor) {
1371   return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
1372 }
1373 
NewEnumValuesByNumber(ParentDescriptor descriptor)1374 PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) {
1375   return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor);
1376 }
1377 
NewEnumValuesSeq(ParentDescriptor descriptor)1378 PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) {
1379   return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor);
1380 }
1381 
1382 }  // namespace enum_descriptor
1383 
1384 namespace oneof_descriptor {
1385 
1386 typedef const OneofDescriptor* ParentDescriptor;
1387 
GetDescriptor(PyContainer * self)1388 static ParentDescriptor GetDescriptor(PyContainer* self) {
1389   return reinterpret_cast<ParentDescriptor>(self->descriptor);
1390 }
1391 
1392 namespace fields {
1393 
1394 typedef const FieldDescriptor* ItemDescriptor;
1395 
Count(PyContainer * self)1396 static int Count(PyContainer* self) {
1397   return GetDescriptor(self)->field_count();
1398 }
1399 
GetByIndex(PyContainer * self,int index)1400 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1401   return GetDescriptor(self)->field(index);
1402 }
1403 
NewObjectFromItem(ItemDescriptor item)1404 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1405   return PyFieldDescriptor_FromDescriptor(item);
1406 }
1407 
GetItemIndex(ItemDescriptor item)1408 static int GetItemIndex(ItemDescriptor item) {
1409   return item->index_in_oneof();
1410 }
1411 
1412 static DescriptorContainerDef ContainerDef = {
1413   "OneofFields",
1414   (CountMethod)Count,
1415   (GetByIndexMethod)GetByIndex,
1416   (GetByNameMethod)NULL,
1417   (GetByCamelcaseNameMethod)NULL,
1418   (GetByNumberMethod)NULL,
1419   (NewObjectFromItemMethod)NewObjectFromItem,
1420   (GetItemNameMethod)NULL,
1421   (GetItemCamelcaseNameMethod)NULL,
1422   (GetItemNumberMethod)NULL,
1423   (GetItemIndexMethod)GetItemIndex,
1424 };
1425 
1426 }  // namespace fields
1427 
NewOneofFieldsSeq(ParentDescriptor descriptor)1428 PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) {
1429   return descriptor::NewSequence(&fields::ContainerDef, descriptor);
1430 }
1431 
1432 }  // namespace oneof_descriptor
1433 
1434 namespace service_descriptor {
1435 
1436 typedef const ServiceDescriptor* ParentDescriptor;
1437 
GetDescriptor(PyContainer * self)1438 static ParentDescriptor GetDescriptor(PyContainer* self) {
1439   return reinterpret_cast<ParentDescriptor>(self->descriptor);
1440 }
1441 
1442 namespace methods {
1443 
1444 typedef const MethodDescriptor* ItemDescriptor;
1445 
Count(PyContainer * self)1446 static int Count(PyContainer* self) {
1447   return GetDescriptor(self)->method_count();
1448 }
1449 
GetByName(PyContainer * self,const string & name)1450 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1451   return GetDescriptor(self)->FindMethodByName(name);
1452 }
1453 
GetByIndex(PyContainer * self,int index)1454 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1455   return GetDescriptor(self)->method(index);
1456 }
1457 
NewObjectFromItem(ItemDescriptor item)1458 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1459   return PyMethodDescriptor_FromDescriptor(item);
1460 }
1461 
GetItemName(ItemDescriptor item)1462 static const string& GetItemName(ItemDescriptor item) {
1463   return item->name();
1464 }
1465 
GetItemIndex(ItemDescriptor item)1466 static int GetItemIndex(ItemDescriptor item) {
1467   return item->index();
1468 }
1469 
1470 static DescriptorContainerDef ContainerDef = {
1471   "ServiceMethods",
1472   (CountMethod)Count,
1473   (GetByIndexMethod)GetByIndex,
1474   (GetByNameMethod)GetByName,
1475   (GetByCamelcaseNameMethod)NULL,
1476   (GetByNumberMethod)NULL,
1477   (NewObjectFromItemMethod)NewObjectFromItem,
1478   (GetItemNameMethod)GetItemName,
1479   (GetItemCamelcaseNameMethod)NULL,
1480   (GetItemNumberMethod)NULL,
1481   (GetItemIndexMethod)GetItemIndex,
1482 };
1483 
1484 }  // namespace methods
1485 
NewServiceMethodsSeq(ParentDescriptor descriptor)1486 PyObject* NewServiceMethodsSeq(ParentDescriptor descriptor) {
1487   return descriptor::NewSequence(&methods::ContainerDef, descriptor);
1488 }
1489 
NewServiceMethodsByName(ParentDescriptor descriptor)1490 PyObject* NewServiceMethodsByName(ParentDescriptor descriptor) {
1491   return descriptor::NewMappingByName(&methods::ContainerDef, descriptor);
1492 }
1493 
1494 }  // namespace service_descriptor
1495 
1496 namespace file_descriptor {
1497 
1498 typedef const FileDescriptor* ParentDescriptor;
1499 
GetDescriptor(PyContainer * self)1500 static ParentDescriptor GetDescriptor(PyContainer* self) {
1501   return reinterpret_cast<ParentDescriptor>(self->descriptor);
1502 }
1503 
1504 namespace messages {
1505 
1506 typedef const Descriptor* ItemDescriptor;
1507 
Count(PyContainer * self)1508 static int Count(PyContainer* self) {
1509   return GetDescriptor(self)->message_type_count();
1510 }
1511 
GetByName(PyContainer * self,const string & name)1512 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1513   return GetDescriptor(self)->FindMessageTypeByName(name);
1514 }
1515 
GetByIndex(PyContainer * self,int index)1516 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1517   return GetDescriptor(self)->message_type(index);
1518 }
1519 
NewObjectFromItem(ItemDescriptor item)1520 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1521   return PyMessageDescriptor_FromDescriptor(item);
1522 }
1523 
GetItemName(ItemDescriptor item)1524 static const string& GetItemName(ItemDescriptor item) {
1525   return item->name();
1526 }
1527 
GetItemIndex(ItemDescriptor item)1528 static int GetItemIndex(ItemDescriptor item) {
1529   return item->index();
1530 }
1531 
1532 static DescriptorContainerDef ContainerDef = {
1533   "FileMessages",
1534   (CountMethod)Count,
1535   (GetByIndexMethod)GetByIndex,
1536   (GetByNameMethod)GetByName,
1537   (GetByCamelcaseNameMethod)NULL,
1538   (GetByNumberMethod)NULL,
1539   (NewObjectFromItemMethod)NewObjectFromItem,
1540   (GetItemNameMethod)GetItemName,
1541   (GetItemCamelcaseNameMethod)NULL,
1542   (GetItemNumberMethod)NULL,
1543   (GetItemIndexMethod)GetItemIndex,
1544 };
1545 
1546 }  // namespace messages
1547 
NewFileMessageTypesByName(ParentDescriptor descriptor)1548 PyObject* NewFileMessageTypesByName(ParentDescriptor descriptor) {
1549   return descriptor::NewMappingByName(&messages::ContainerDef, descriptor);
1550 }
1551 
1552 namespace enums {
1553 
1554 typedef const EnumDescriptor* ItemDescriptor;
1555 
Count(PyContainer * self)1556 static int Count(PyContainer* self) {
1557   return GetDescriptor(self)->enum_type_count();
1558 }
1559 
GetByName(PyContainer * self,const string & name)1560 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1561   return GetDescriptor(self)->FindEnumTypeByName(name);
1562 }
1563 
GetByIndex(PyContainer * self,int index)1564 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1565   return GetDescriptor(self)->enum_type(index);
1566 }
1567 
NewObjectFromItem(ItemDescriptor item)1568 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1569   return PyEnumDescriptor_FromDescriptor(item);
1570 }
1571 
GetItemName(ItemDescriptor item)1572 static const string& GetItemName(ItemDescriptor item) {
1573   return item->name();
1574 }
1575 
GetItemIndex(ItemDescriptor item)1576 static int GetItemIndex(ItemDescriptor item) {
1577   return item->index();
1578 }
1579 
1580 static DescriptorContainerDef ContainerDef = {
1581   "FileEnums",
1582   (CountMethod)Count,
1583   (GetByIndexMethod)GetByIndex,
1584   (GetByNameMethod)GetByName,
1585   (GetByCamelcaseNameMethod)NULL,
1586   (GetByNumberMethod)NULL,
1587   (NewObjectFromItemMethod)NewObjectFromItem,
1588   (GetItemNameMethod)GetItemName,
1589   (GetItemCamelcaseNameMethod)NULL,
1590   (GetItemNumberMethod)NULL,
1591   (GetItemIndexMethod)GetItemIndex,
1592 };
1593 
1594 }  // namespace enums
1595 
NewFileEnumTypesByName(ParentDescriptor descriptor)1596 PyObject* NewFileEnumTypesByName(ParentDescriptor descriptor) {
1597   return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
1598 }
1599 
1600 namespace extensions {
1601 
1602 typedef const FieldDescriptor* ItemDescriptor;
1603 
Count(PyContainer * self)1604 static int Count(PyContainer* self) {
1605   return GetDescriptor(self)->extension_count();
1606 }
1607 
GetByName(PyContainer * self,const string & name)1608 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1609   return GetDescriptor(self)->FindExtensionByName(name);
1610 }
1611 
GetByIndex(PyContainer * self,int index)1612 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1613   return GetDescriptor(self)->extension(index);
1614 }
1615 
NewObjectFromItem(ItemDescriptor item)1616 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1617   return PyFieldDescriptor_FromDescriptor(item);
1618 }
1619 
GetItemName(ItemDescriptor item)1620 static const string& GetItemName(ItemDescriptor item) {
1621   return item->name();
1622 }
1623 
GetItemIndex(ItemDescriptor item)1624 static int GetItemIndex(ItemDescriptor item) {
1625   return item->index();
1626 }
1627 
1628 static DescriptorContainerDef ContainerDef = {
1629   "FileExtensions",
1630   (CountMethod)Count,
1631   (GetByIndexMethod)GetByIndex,
1632   (GetByNameMethod)GetByName,
1633   (GetByCamelcaseNameMethod)NULL,
1634   (GetByNumberMethod)NULL,
1635   (NewObjectFromItemMethod)NewObjectFromItem,
1636   (GetItemNameMethod)GetItemName,
1637   (GetItemCamelcaseNameMethod)NULL,
1638   (GetItemNumberMethod)NULL,
1639   (GetItemIndexMethod)GetItemIndex,
1640 };
1641 
1642 }  // namespace extensions
1643 
NewFileExtensionsByName(ParentDescriptor descriptor)1644 PyObject* NewFileExtensionsByName(ParentDescriptor descriptor) {
1645   return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
1646 }
1647 
1648 namespace services {
1649 
1650 typedef const ServiceDescriptor* ItemDescriptor;
1651 
Count(PyContainer * self)1652 static int Count(PyContainer* self) {
1653   return GetDescriptor(self)->service_count();
1654 }
1655 
GetByName(PyContainer * self,const string & name)1656 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1657   return GetDescriptor(self)->FindServiceByName(name);
1658 }
1659 
GetByIndex(PyContainer * self,int index)1660 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1661   return GetDescriptor(self)->service(index);
1662 }
1663 
NewObjectFromItem(ItemDescriptor item)1664 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1665   return PyServiceDescriptor_FromDescriptor(item);
1666 }
1667 
GetItemName(ItemDescriptor item)1668 static const string& GetItemName(ItemDescriptor item) {
1669   return item->name();
1670 }
1671 
GetItemIndex(ItemDescriptor item)1672 static int GetItemIndex(ItemDescriptor item) {
1673   return item->index();
1674 }
1675 
1676 static DescriptorContainerDef ContainerDef = {
1677   "FileServices",
1678   (CountMethod)Count,
1679   (GetByIndexMethod)GetByIndex,
1680   (GetByNameMethod)GetByName,
1681   (GetByCamelcaseNameMethod)NULL,
1682   (GetByNumberMethod)NULL,
1683   (NewObjectFromItemMethod)NewObjectFromItem,
1684   (GetItemNameMethod)GetItemName,
1685   (GetItemCamelcaseNameMethod)NULL,
1686   (GetItemNumberMethod)NULL,
1687   (GetItemIndexMethod)GetItemIndex,
1688 };
1689 
1690 }  // namespace services
1691 
NewFileServicesByName(const FileDescriptor * descriptor)1692 PyObject* NewFileServicesByName(const FileDescriptor* descriptor) {
1693   return descriptor::NewMappingByName(&services::ContainerDef, descriptor);
1694 }
1695 
1696 namespace dependencies {
1697 
1698 typedef const FileDescriptor* ItemDescriptor;
1699 
Count(PyContainer * self)1700 static int Count(PyContainer* self) {
1701   return GetDescriptor(self)->dependency_count();
1702 }
1703 
GetByIndex(PyContainer * self,int index)1704 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1705   return GetDescriptor(self)->dependency(index);
1706 }
1707 
NewObjectFromItem(ItemDescriptor item)1708 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1709   return PyFileDescriptor_FromDescriptor(item);
1710 }
1711 
1712 static DescriptorContainerDef ContainerDef = {
1713   "FileDependencies",
1714   (CountMethod)Count,
1715   (GetByIndexMethod)GetByIndex,
1716   (GetByNameMethod)NULL,
1717   (GetByCamelcaseNameMethod)NULL,
1718   (GetByNumberMethod)NULL,
1719   (NewObjectFromItemMethod)NewObjectFromItem,
1720   (GetItemNameMethod)NULL,
1721   (GetItemCamelcaseNameMethod)NULL,
1722   (GetItemNumberMethod)NULL,
1723   (GetItemIndexMethod)NULL,
1724 };
1725 
1726 }  // namespace dependencies
1727 
NewFileDependencies(const FileDescriptor * descriptor)1728 PyObject* NewFileDependencies(const FileDescriptor* descriptor) {
1729   return descriptor::NewSequence(&dependencies::ContainerDef, descriptor);
1730 }
1731 
1732 namespace public_dependencies {
1733 
1734 typedef const FileDescriptor* ItemDescriptor;
1735 
Count(PyContainer * self)1736 static int Count(PyContainer* self) {
1737   return GetDescriptor(self)->public_dependency_count();
1738 }
1739 
GetByIndex(PyContainer * self,int index)1740 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1741   return GetDescriptor(self)->public_dependency(index);
1742 }
1743 
NewObjectFromItem(ItemDescriptor item)1744 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1745   return PyFileDescriptor_FromDescriptor(item);
1746 }
1747 
1748 static DescriptorContainerDef ContainerDef = {
1749   "FilePublicDependencies",
1750   (CountMethod)Count,
1751   (GetByIndexMethod)GetByIndex,
1752   (GetByNameMethod)NULL,
1753   (GetByCamelcaseNameMethod)NULL,
1754   (GetByNumberMethod)NULL,
1755   (NewObjectFromItemMethod)NewObjectFromItem,
1756   (GetItemNameMethod)NULL,
1757   (GetItemCamelcaseNameMethod)NULL,
1758   (GetItemNumberMethod)NULL,
1759   (GetItemIndexMethod)NULL,
1760 };
1761 
1762 }  // namespace public_dependencies
1763 
NewFilePublicDependencies(const FileDescriptor * descriptor)1764 PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) {
1765   return descriptor::NewSequence(&public_dependencies::ContainerDef,
1766                                  descriptor);
1767 }
1768 
1769 }  // namespace file_descriptor
1770 
1771 
1772 // Register all implementations
1773 
InitDescriptorMappingTypes()1774 bool InitDescriptorMappingTypes() {
1775   if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0)
1776     return false;
1777   if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0)
1778     return false;
1779   if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0)
1780     return false;
1781   return true;
1782 }
1783 
1784 }  // namespace python
1785 }  // namespace protobuf
1786 }  // namespace google
1787