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