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