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