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