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