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