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