• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "python/descriptor_containers.h"
9 
10 #include "python/descriptor.h"
11 #include "python/protobuf.h"
12 #include "upb/reflection/def.h"
13 
14 // Implements __repr__ as str(dict(self)).
PyUpb_DescriptorMap_Repr(PyObject * _self)15 static PyObject* PyUpb_DescriptorMap_Repr(PyObject* _self) {
16   PyObject* dict = PyDict_New();
17   PyObject* ret = NULL;
18   if (!dict) goto err;
19   if (PyDict_Merge(dict, _self, 1) != 0) goto err;
20   ret = PyObject_Str(dict);
21 
22 err:
23   Py_XDECREF(dict);
24   return ret;
25 }
26 
27 // -----------------------------------------------------------------------------
28 // ByNameIterator
29 // -----------------------------------------------------------------------------
30 
31 typedef struct {
32   PyObject_HEAD;
33   const PyUpb_ByNameMap_Funcs* funcs;
34   const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
35   PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
36   int index;             // Current iterator index.
37 } PyUpb_ByNameIterator;
38 
PyUpb_ByNameIterator_Self(PyObject * obj)39 static PyUpb_ByNameIterator* PyUpb_ByNameIterator_Self(PyObject* obj) {
40   assert(Py_TYPE(obj) == PyUpb_ModuleState_Get()->by_name_iterator_type);
41   return (PyUpb_ByNameIterator*)obj;
42 }
43 
PyUpb_ByNameIterator_Dealloc(PyObject * _self)44 static void PyUpb_ByNameIterator_Dealloc(PyObject* _self) {
45   PyUpb_ByNameIterator* self = PyUpb_ByNameIterator_Self(_self);
46   Py_DECREF(self->parent_obj);
47   PyUpb_Dealloc(self);
48 }
49 
PyUpb_ByNameIterator_New(const PyUpb_ByNameMap_Funcs * funcs,const void * parent,PyObject * parent_obj)50 static PyObject* PyUpb_ByNameIterator_New(const PyUpb_ByNameMap_Funcs* funcs,
51                                           const void* parent,
52                                           PyObject* parent_obj) {
53   PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
54   PyUpb_ByNameIterator* iter =
55       (void*)PyType_GenericAlloc(s->by_name_iterator_type, 0);
56   iter->funcs = funcs;
57   iter->parent = parent;
58   iter->parent_obj = parent_obj;
59   iter->index = 0;
60   Py_INCREF(iter->parent_obj);
61   return &iter->ob_base;
62 }
63 
PyUpb_ByNameIterator_IterNext(PyObject * _self)64 static PyObject* PyUpb_ByNameIterator_IterNext(PyObject* _self) {
65   PyUpb_ByNameIterator* self = PyUpb_ByNameIterator_Self(_self);
66   int size = self->funcs->base.get_elem_count(self->parent);
67   if (self->index >= size) return NULL;
68   const void* elem = self->funcs->base.index(self->parent, self->index);
69   self->index++;
70   return PyUnicode_FromString(self->funcs->get_elem_name(elem));
71 }
72 
73 static PyType_Slot PyUpb_ByNameIterator_Slots[] = {
74     {Py_tp_dealloc, PyUpb_ByNameIterator_Dealloc},
75     {Py_tp_iter, PyObject_SelfIter},
76     {Py_tp_iternext, PyUpb_ByNameIterator_IterNext},
77     {0, NULL}};
78 
79 static PyType_Spec PyUpb_ByNameIterator_Spec = {
80     PYUPB_MODULE_NAME "._ByNameIterator",  // tp_name
81     sizeof(PyUpb_ByNameIterator),          // tp_basicsize
82     0,                                     // tp_itemsize
83     Py_TPFLAGS_DEFAULT,                    // tp_flags
84     PyUpb_ByNameIterator_Slots,
85 };
86 
87 // -----------------------------------------------------------------------------
88 // ByNumberIterator
89 // -----------------------------------------------------------------------------
90 
91 typedef struct {
92   PyObject_HEAD;
93   const PyUpb_ByNumberMap_Funcs* funcs;
94   const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
95   PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
96   int index;             // Current iterator index.
97 } PyUpb_ByNumberIterator;
98 
PyUpb_ByNumberIterator_Self(PyObject * obj)99 static PyUpb_ByNumberIterator* PyUpb_ByNumberIterator_Self(PyObject* obj) {
100   assert(Py_TYPE(obj) == PyUpb_ModuleState_Get()->by_number_iterator_type);
101   return (PyUpb_ByNumberIterator*)obj;
102 }
103 
PyUpb_ByNumberIterator_Dealloc(PyObject * _self)104 static void PyUpb_ByNumberIterator_Dealloc(PyObject* _self) {
105   PyUpb_ByNumberIterator* self = PyUpb_ByNumberIterator_Self(_self);
106   Py_DECREF(self->parent_obj);
107   PyUpb_Dealloc(self);
108 }
109 
PyUpb_ByNumberIterator_New(const PyUpb_ByNumberMap_Funcs * funcs,const void * parent,PyObject * parent_obj)110 static PyObject* PyUpb_ByNumberIterator_New(
111     const PyUpb_ByNumberMap_Funcs* funcs, const void* parent,
112     PyObject* parent_obj) {
113   PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
114   PyUpb_ByNumberIterator* iter =
115       (void*)PyType_GenericAlloc(s->by_number_iterator_type, 0);
116   iter->funcs = funcs;
117   iter->parent = parent;
118   iter->parent_obj = parent_obj;
119   iter->index = 0;
120   Py_INCREF(iter->parent_obj);
121   return &iter->ob_base;
122 }
123 
PyUpb_ByNumberIterator_IterNext(PyObject * _self)124 static PyObject* PyUpb_ByNumberIterator_IterNext(PyObject* _self) {
125   PyUpb_ByNumberIterator* self = PyUpb_ByNumberIterator_Self(_self);
126   int size = self->funcs->base.get_elem_count(self->parent);
127   if (self->index >= size) return NULL;
128   const void* elem = self->funcs->base.index(self->parent, self->index);
129   self->index++;
130   return PyLong_FromLong(self->funcs->get_elem_num(elem));
131 }
132 
133 static PyType_Slot PyUpb_ByNumberIterator_Slots[] = {
134     {Py_tp_dealloc, PyUpb_ByNumberIterator_Dealloc},
135     {Py_tp_iter, PyObject_SelfIter},
136     {Py_tp_iternext, PyUpb_ByNumberIterator_IterNext},
137     {0, NULL}};
138 
139 static PyType_Spec PyUpb_ByNumberIterator_Spec = {
140     PYUPB_MODULE_NAME "._ByNumberIterator",  // tp_name
141     sizeof(PyUpb_ByNumberIterator),          // tp_basicsize
142     0,                                       // tp_itemsize
143     Py_TPFLAGS_DEFAULT,                      // tp_flags
144     PyUpb_ByNumberIterator_Slots,
145 };
146 
147 // -----------------------------------------------------------------------------
148 // GenericSequence
149 // -----------------------------------------------------------------------------
150 
151 typedef struct {
152   PyObject_HEAD;
153   const PyUpb_GenericSequence_Funcs* funcs;
154   const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
155   PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
156 } PyUpb_GenericSequence;
157 
PyUpb_GenericSequence_Self(PyObject * obj)158 PyUpb_GenericSequence* PyUpb_GenericSequence_Self(PyObject* obj) {
159   assert(Py_TYPE(obj) == PyUpb_ModuleState_Get()->generic_sequence_type);
160   return (PyUpb_GenericSequence*)obj;
161 }
162 
PyUpb_GenericSequence_Dealloc(PyObject * _self)163 static void PyUpb_GenericSequence_Dealloc(PyObject* _self) {
164   PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
165   Py_CLEAR(self->parent_obj);
166   PyUpb_Dealloc(self);
167 }
168 
PyUpb_GenericSequence_New(const PyUpb_GenericSequence_Funcs * funcs,const void * parent,PyObject * parent_obj)169 PyObject* PyUpb_GenericSequence_New(const PyUpb_GenericSequence_Funcs* funcs,
170                                     const void* parent, PyObject* parent_obj) {
171   PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
172   PyUpb_GenericSequence* seq =
173       (PyUpb_GenericSequence*)PyType_GenericAlloc(s->generic_sequence_type, 0);
174   seq->funcs = funcs;
175   seq->parent = parent;
176   seq->parent_obj = parent_obj;
177   Py_INCREF(parent_obj);
178   return &seq->ob_base;
179 }
180 
PyUpb_GenericSequence_Length(PyObject * _self)181 static Py_ssize_t PyUpb_GenericSequence_Length(PyObject* _self) {
182   PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
183   return self->funcs->get_elem_count(self->parent);
184 }
185 
PyUpb_GenericSequence_GetItem(PyObject * _self,Py_ssize_t index)186 static PyObject* PyUpb_GenericSequence_GetItem(PyObject* _self,
187                                                Py_ssize_t index) {
188   PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
189   Py_ssize_t size = self->funcs->get_elem_count(self->parent);
190   if (index < 0) {
191     index += size;
192   }
193   if (index < 0 || index >= size) {
194     PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
195     return NULL;
196   }
197   const void* elem = self->funcs->index(self->parent, index);
198   return self->funcs->get_elem_wrapper(elem);
199 }
200 
201 // A sequence container can only be equal to another sequence container, or (for
202 // backward compatibility) to a list containing the same items.
203 // Returns 1 if equal, 0 if unequal, -1 on error.
PyUpb_GenericSequence_IsEqual(PyUpb_GenericSequence * self,PyObject * other)204 static int PyUpb_GenericSequence_IsEqual(PyUpb_GenericSequence* self,
205                                          PyObject* other) {
206   // Check the identity of C++ pointers.
207   if (PyObject_TypeCheck(other, Py_TYPE(self))) {
208     PyUpb_GenericSequence* other_seq = (void*)other;
209     return self->parent == other_seq->parent && self->funcs == other_seq->funcs;
210   }
211 
212   if (!PyList_Check(other)) return 0;
213 
214   // return list(self) == other
215   // We can clamp `i` to int because GenericSequence uses int for size (this
216   // is useful when we do int iteration below).
217   int n = PyUpb_GenericSequence_Length((PyObject*)self);
218   if ((Py_ssize_t)n != PyList_Size(other)) {
219     return false;
220   }
221 
222   PyObject* item1;
223   for (int i = 0; i < n; i++) {
224     item1 = PyUpb_GenericSequence_GetItem((PyObject*)self, i);
225     PyObject* item2 = PyList_GetItem(other, i);
226     if (!item1 || !item2) goto error;
227     int cmp = PyObject_RichCompareBool(item1, item2, Py_EQ);
228     Py_DECREF(item1);
229     if (cmp != 1) return cmp;
230   }
231   // All items were found and equal
232   return 1;
233 
234 error:
235   Py_XDECREF(item1);
236   return -1;
237 }
238 
PyUpb_GenericSequence_RichCompare(PyObject * _self,PyObject * other,int opid)239 static PyObject* PyUpb_GenericSequence_RichCompare(PyObject* _self,
240                                                    PyObject* other, int opid) {
241   PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
242   if (opid != Py_EQ && opid != Py_NE) {
243     Py_RETURN_NOTIMPLEMENTED;
244   }
245   bool ret = PyUpb_GenericSequence_IsEqual(self, other);
246   if (opid == Py_NE) ret = !ret;
247   return PyBool_FromLong(ret);
248 }
249 
PyUpb_GenericSequence_Subscript(PyObject * _self,PyObject * item)250 static PyObject* PyUpb_GenericSequence_Subscript(PyObject* _self,
251                                                  PyObject* item) {
252   PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
253   Py_ssize_t size = self->funcs->get_elem_count(self->parent);
254   Py_ssize_t idx, count, step;
255   if (!PyUpb_IndexToRange(item, size, &idx, &count, &step)) return NULL;
256   if (step == 0) {
257     return PyUpb_GenericSequence_GetItem(_self, idx);
258   } else {
259     PyObject* list = PyList_New(count);
260     for (Py_ssize_t i = 0; i < count; i++, idx += step) {
261       const void* elem = self->funcs->index(self->parent, idx);
262       PyList_SetItem(list, i, self->funcs->get_elem_wrapper(elem));
263     }
264     return list;
265   }
266 }
267 
268 // Linear search.  Could optimize this in some cases (defs that have index),
269 // but not all (FileDescriptor.dependencies).
PyUpb_GenericSequence_Find(PyObject * _self,PyObject * item)270 static int PyUpb_GenericSequence_Find(PyObject* _self, PyObject* item) {
271   PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
272   const void* item_ptr = PyUpb_AnyDescriptor_GetDef(item);
273   int count = self->funcs->get_elem_count(self->parent);
274   for (int i = 0; i < count; i++) {
275     if (self->funcs->index(self->parent, i) == item_ptr) {
276       return i;
277     }
278   }
279   return -1;
280 }
281 
PyUpb_GenericSequence_Index(PyObject * self,PyObject * item)282 static PyObject* PyUpb_GenericSequence_Index(PyObject* self, PyObject* item) {
283   int position = PyUpb_GenericSequence_Find(self, item);
284   if (position < 0) {
285     PyErr_SetNone(PyExc_ValueError);
286     return NULL;
287   } else {
288     return PyLong_FromLong(position);
289   }
290 }
291 
PyUpb_GenericSequence_Count(PyObject * _self,PyObject * item)292 static PyObject* PyUpb_GenericSequence_Count(PyObject* _self, PyObject* item) {
293   PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
294   const void* item_ptr = PyUpb_AnyDescriptor_GetDef(item);
295   int n = self->funcs->get_elem_count(self->parent);
296   int count = 0;
297   for (int i = 0; i < n; i++) {
298     if (self->funcs->index(self->parent, i) == item_ptr) {
299       count++;
300     }
301   }
302   return PyLong_FromLong(count);
303 }
304 
PyUpb_GenericSequence_Append(PyObject * self,PyObject * args)305 static PyObject* PyUpb_GenericSequence_Append(PyObject* self, PyObject* args) {
306   PyErr_Format(PyExc_TypeError, "'%R' is not a mutable sequence", self);
307   return NULL;
308 }
309 
310 static PyMethodDef PyUpb_GenericSequence_Methods[] = {
311     {"index", PyUpb_GenericSequence_Index, METH_O},
312     {"count", PyUpb_GenericSequence_Count, METH_O},
313     {"append", PyUpb_GenericSequence_Append, METH_O},
314     // This was implemented for Python/C++ but so far has not been required.
315     //{ "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
316     {NULL}};
317 
318 static PyType_Slot PyUpb_GenericSequence_Slots[] = {
319     {Py_tp_dealloc, &PyUpb_GenericSequence_Dealloc},
320     {Py_tp_methods, &PyUpb_GenericSequence_Methods},
321     {Py_sq_length, PyUpb_GenericSequence_Length},
322     {Py_sq_item, PyUpb_GenericSequence_GetItem},
323     {Py_tp_richcompare, &PyUpb_GenericSequence_RichCompare},
324     {Py_mp_subscript, PyUpb_GenericSequence_Subscript},
325     // These were implemented for Python/C++ but so far have not been required.
326     // {Py_tp_repr, &PyUpb_GenericSequence_Repr},
327     // {Py_sq_contains, PyUpb_GenericSequence_Contains},
328     // {Py_mp_ass_subscript, PyUpb_GenericSequence_AssignSubscript},
329     {0, NULL},
330 };
331 
332 static PyType_Spec PyUpb_GenericSequence_Spec = {
333     PYUPB_MODULE_NAME "._GenericSequence",  // tp_name
334     sizeof(PyUpb_GenericSequence),          // tp_basicsize
335     0,                                      // tp_itemsize
336     Py_TPFLAGS_DEFAULT,                     // tp_flags
337     PyUpb_GenericSequence_Slots,
338 };
339 
340 // -----------------------------------------------------------------------------
341 // ByNameMap
342 // -----------------------------------------------------------------------------
343 
344 typedef struct {
345   PyObject_HEAD;
346   const PyUpb_ByNameMap_Funcs* funcs;
347   const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
348   PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
349 } PyUpb_ByNameMap;
350 
PyUpb_ByNameMap_Self(PyObject * obj)351 PyUpb_ByNameMap* PyUpb_ByNameMap_Self(PyObject* obj) {
352   assert(Py_TYPE(obj) == PyUpb_ModuleState_Get()->by_name_map_type);
353   return (PyUpb_ByNameMap*)obj;
354 }
355 
PyUpb_ByNameMap_Dealloc(PyObject * _self)356 static void PyUpb_ByNameMap_Dealloc(PyObject* _self) {
357   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
358   Py_DECREF(self->parent_obj);
359   PyUpb_Dealloc(self);
360 }
361 
PyUpb_ByNameMap_New(const PyUpb_ByNameMap_Funcs * funcs,const void * parent,PyObject * parent_obj)362 PyObject* PyUpb_ByNameMap_New(const PyUpb_ByNameMap_Funcs* funcs,
363                               const void* parent, PyObject* parent_obj) {
364   PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
365   PyUpb_ByNameMap* map = (void*)PyType_GenericAlloc(s->by_name_map_type, 0);
366   map->funcs = funcs;
367   map->parent = parent;
368   map->parent_obj = parent_obj;
369   Py_INCREF(parent_obj);
370   return &map->ob_base;
371 }
372 
PyUpb_ByNameMap_Length(PyObject * _self)373 static Py_ssize_t PyUpb_ByNameMap_Length(PyObject* _self) {
374   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
375   return self->funcs->base.get_elem_count(self->parent);
376 }
377 
PyUpb_ByNameMap_Subscript(PyObject * _self,PyObject * key)378 static PyObject* PyUpb_ByNameMap_Subscript(PyObject* _self, PyObject* key) {
379   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
380   const char* name = PyUpb_GetStrData(key);
381   const void* elem = name ? self->funcs->lookup(self->parent, name) : NULL;
382 
383   if (!name && PyObject_Hash(key) == -1) return NULL;
384 
385   if (elem) {
386     return self->funcs->base.get_elem_wrapper(elem);
387   } else {
388     PyErr_SetObject(PyExc_KeyError, key);
389     return NULL;
390   }
391 }
392 
PyUpb_ByNameMap_AssignSubscript(PyObject * self,PyObject * key,PyObject * value)393 static int PyUpb_ByNameMap_AssignSubscript(PyObject* self, PyObject* key,
394                                            PyObject* value) {
395   PyErr_Format(PyExc_TypeError, PYUPB_MODULE_NAME
396                ".ByNameMap' object does not support item assignment");
397   return -1;
398 }
399 
PyUpb_ByNameMap_Contains(PyObject * _self,PyObject * key)400 static int PyUpb_ByNameMap_Contains(PyObject* _self, PyObject* key) {
401   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
402   const char* name = PyUpb_GetStrData(key);
403   const void* elem = name ? self->funcs->lookup(self->parent, name) : NULL;
404   if (!name && PyObject_Hash(key) == -1) return -1;
405   return elem ? 1 : 0;
406 }
407 
PyUpb_ByNameMap_Get(PyObject * _self,PyObject * args)408 static PyObject* PyUpb_ByNameMap_Get(PyObject* _self, PyObject* args) {
409   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
410   PyObject* key;
411   PyObject* default_value = Py_None;
412   if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
413     return NULL;
414   }
415 
416   const char* name = PyUpb_GetStrData(key);
417   const void* elem = name ? self->funcs->lookup(self->parent, name) : NULL;
418 
419   if (!name && PyObject_Hash(key) == -1) return NULL;
420 
421   if (elem) {
422     return self->funcs->base.get_elem_wrapper(elem);
423   } else {
424     Py_INCREF(default_value);
425     return default_value;
426   }
427 }
428 
PyUpb_ByNameMap_GetIter(PyObject * _self)429 static PyObject* PyUpb_ByNameMap_GetIter(PyObject* _self) {
430   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
431   return PyUpb_ByNameIterator_New(self->funcs, self->parent, self->parent_obj);
432 }
433 
PyUpb_ByNameMap_Keys(PyObject * _self,PyObject * args)434 static PyObject* PyUpb_ByNameMap_Keys(PyObject* _self, PyObject* args) {
435   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
436   int n = self->funcs->base.get_elem_count(self->parent);
437   PyObject* ret = PyList_New(n);
438   if (!ret) return NULL;
439   for (int i = 0; i < n; i++) {
440     const void* elem = self->funcs->base.index(self->parent, i);
441     PyObject* key = PyUnicode_FromString(self->funcs->get_elem_name(elem));
442     if (!key) goto error;
443     PyList_SetItem(ret, i, key);
444   }
445   return ret;
446 
447 error:
448   Py_XDECREF(ret);
449   return NULL;
450 }
451 
PyUpb_ByNameMap_Values(PyObject * _self,PyObject * args)452 static PyObject* PyUpb_ByNameMap_Values(PyObject* _self, PyObject* args) {
453   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
454   int n = self->funcs->base.get_elem_count(self->parent);
455   PyObject* ret = PyList_New(n);
456   if (!ret) return NULL;
457   for (int i = 0; i < n; i++) {
458     const void* elem = self->funcs->base.index(self->parent, i);
459     PyObject* py_elem = self->funcs->base.get_elem_wrapper(elem);
460     if (!py_elem) goto error;
461     PyList_SetItem(ret, i, py_elem);
462   }
463   return ret;
464 
465 error:
466   Py_XDECREF(ret);
467   return NULL;
468 }
469 
PyUpb_ByNameMap_Items(PyObject * _self,PyObject * args)470 static PyObject* PyUpb_ByNameMap_Items(PyObject* _self, PyObject* args) {
471   PyUpb_ByNameMap* self = (PyUpb_ByNameMap*)_self;
472   int n = self->funcs->base.get_elem_count(self->parent);
473   PyObject* ret = PyList_New(n);
474   PyObject* item;
475   PyObject* py_elem;
476   if (!ret) return NULL;
477   for (int i = 0; i < n; i++) {
478     const void* elem = self->funcs->base.index(self->parent, i);
479     item = PyTuple_New(2);
480     py_elem = self->funcs->base.get_elem_wrapper(elem);
481     if (!item || !py_elem) goto error;
482     PyTuple_SetItem(item, 0,
483                     PyUnicode_FromString(self->funcs->get_elem_name(elem)));
484     PyTuple_SetItem(item, 1, py_elem);
485     PyList_SetItem(ret, i, item);
486   }
487   return ret;
488 
489 error:
490   Py_XDECREF(py_elem);
491   Py_XDECREF(item);
492   Py_XDECREF(ret);
493   return NULL;
494 }
495 
496 // A mapping container can only be equal to another mapping container, or (for
497 // backward compatibility) to a dict containing the same items.
498 // Returns 1 if equal, 0 if unequal, -1 on error.
PyUpb_ByNameMap_IsEqual(PyUpb_ByNameMap * self,PyObject * other)499 static int PyUpb_ByNameMap_IsEqual(PyUpb_ByNameMap* self, PyObject* other) {
500   // Check the identity of C++ pointers.
501   if (PyObject_TypeCheck(other, Py_TYPE(self))) {
502     PyUpb_ByNameMap* other_map = (void*)other;
503     return self->parent == other_map->parent && self->funcs == other_map->funcs;
504   }
505 
506   if (!PyDict_Check(other)) return 0;
507 
508   PyObject* self_dict = PyDict_New();
509   PyDict_Merge(self_dict, (PyObject*)self, 0);
510   int eq = PyObject_RichCompareBool(self_dict, other, Py_EQ);
511   Py_DECREF(self_dict);
512   return eq;
513 }
514 
PyUpb_ByNameMap_RichCompare(PyObject * _self,PyObject * other,int opid)515 static PyObject* PyUpb_ByNameMap_RichCompare(PyObject* _self, PyObject* other,
516                                              int opid) {
517   PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
518   if (opid != Py_EQ && opid != Py_NE) {
519     Py_RETURN_NOTIMPLEMENTED;
520   }
521   bool ret = PyUpb_ByNameMap_IsEqual(self, other);
522   if (opid == Py_NE) ret = !ret;
523   return PyBool_FromLong(ret);
524 }
525 
526 static PyMethodDef PyUpb_ByNameMap_Methods[] = {
527     {"get", (PyCFunction)&PyUpb_ByNameMap_Get, METH_VARARGS},
528     {"keys", PyUpb_ByNameMap_Keys, METH_NOARGS},
529     {"values", PyUpb_ByNameMap_Values, METH_NOARGS},
530     {"items", PyUpb_ByNameMap_Items, METH_NOARGS},
531     {NULL}};
532 
533 static PyType_Slot PyUpb_ByNameMap_Slots[] = {
534     {Py_mp_ass_subscript, PyUpb_ByNameMap_AssignSubscript},
535     {Py_mp_length, PyUpb_ByNameMap_Length},
536     {Py_mp_subscript, PyUpb_ByNameMap_Subscript},
537     {Py_sq_contains, &PyUpb_ByNameMap_Contains},
538     {Py_tp_dealloc, &PyUpb_ByNameMap_Dealloc},
539     {Py_tp_iter, PyUpb_ByNameMap_GetIter},
540     {Py_tp_methods, &PyUpb_ByNameMap_Methods},
541     {Py_tp_repr, &PyUpb_DescriptorMap_Repr},
542     {Py_tp_richcompare, &PyUpb_ByNameMap_RichCompare},
543     {0, NULL},
544 };
545 
546 static PyType_Spec PyUpb_ByNameMap_Spec = {
547     PYUPB_MODULE_NAME "._ByNameMap",  // tp_name
548     sizeof(PyUpb_ByNameMap),          // tp_basicsize
549     0,                                // tp_itemsize
550     Py_TPFLAGS_DEFAULT,               // tp_flags
551     PyUpb_ByNameMap_Slots,
552 };
553 
554 // -----------------------------------------------------------------------------
555 // ByNumberMap
556 // -----------------------------------------------------------------------------
557 
558 typedef struct {
559   PyObject_HEAD;
560   const PyUpb_ByNumberMap_Funcs* funcs;
561   const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
562   PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
563 } PyUpb_ByNumberMap;
564 
PyUpb_ByNumberMap_Self(PyObject * obj)565 PyUpb_ByNumberMap* PyUpb_ByNumberMap_Self(PyObject* obj) {
566   assert(Py_TYPE(obj) == PyUpb_ModuleState_Get()->by_number_map_type);
567   return (PyUpb_ByNumberMap*)obj;
568 }
569 
PyUpb_ByNumberMap_New(const PyUpb_ByNumberMap_Funcs * funcs,const void * parent,PyObject * parent_obj)570 PyObject* PyUpb_ByNumberMap_New(const PyUpb_ByNumberMap_Funcs* funcs,
571                                 const void* parent, PyObject* parent_obj) {
572   PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
573   PyUpb_ByNumberMap* map = (void*)PyType_GenericAlloc(s->by_number_map_type, 0);
574   map->funcs = funcs;
575   map->parent = parent;
576   map->parent_obj = parent_obj;
577   Py_INCREF(parent_obj);
578   return &map->ob_base;
579 }
580 
PyUpb_ByNumberMap_Dealloc(PyObject * _self)581 static void PyUpb_ByNumberMap_Dealloc(PyObject* _self) {
582   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
583   Py_DECREF(self->parent_obj);
584   PyUpb_Dealloc(self);
585 }
586 
PyUpb_ByNumberMap_Length(PyObject * _self)587 static Py_ssize_t PyUpb_ByNumberMap_Length(PyObject* _self) {
588   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
589   return self->funcs->base.get_elem_count(self->parent);
590 }
591 
PyUpb_ByNumberMap_LookupHelper(PyUpb_ByNumberMap * self,PyObject * key)592 static const void* PyUpb_ByNumberMap_LookupHelper(PyUpb_ByNumberMap* self,
593                                                   PyObject* key) {
594   long num = PyLong_AsLong(key);
595   if (num == -1 && PyErr_Occurred()) {
596     PyErr_Clear();
597     // Ensure that the key is hashable (this will raise an error if not).
598     PyObject_Hash(key);
599     return NULL;
600   } else {
601     return self->funcs->lookup(self->parent, num);
602   }
603 }
604 
PyUpb_ByNumberMap_Subscript(PyObject * _self,PyObject * key)605 static PyObject* PyUpb_ByNumberMap_Subscript(PyObject* _self, PyObject* key) {
606   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
607   const void* elem = PyUpb_ByNumberMap_LookupHelper(self, key);
608   if (elem) {
609     return self->funcs->base.get_elem_wrapper(elem);
610   } else {
611     if (!PyErr_Occurred()) {
612       PyErr_SetObject(PyExc_KeyError, key);
613     }
614     return NULL;
615   }
616 }
617 
PyUpb_ByNumberMap_AssignSubscript(PyObject * self,PyObject * key,PyObject * value)618 static int PyUpb_ByNumberMap_AssignSubscript(PyObject* self, PyObject* key,
619                                              PyObject* value) {
620   PyErr_Format(PyExc_TypeError, PYUPB_MODULE_NAME
621                ".ByNumberMap' object does not support item assignment");
622   return -1;
623 }
624 
PyUpb_ByNumberMap_Get(PyObject * _self,PyObject * args)625 static PyObject* PyUpb_ByNumberMap_Get(PyObject* _self, PyObject* args) {
626   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
627   PyObject* key;
628   PyObject* default_value = Py_None;
629   if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
630     return NULL;
631   }
632 
633   const void* elem = PyUpb_ByNumberMap_LookupHelper(self, key);
634   if (elem) {
635     return self->funcs->base.get_elem_wrapper(elem);
636   } else if (PyErr_Occurred()) {
637     return NULL;
638   } else {
639     return PyUpb_NewRef(default_value);
640   }
641 }
642 
PyUpb_ByNumberMap_GetIter(PyObject * _self)643 static PyObject* PyUpb_ByNumberMap_GetIter(PyObject* _self) {
644   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
645   return PyUpb_ByNumberIterator_New(self->funcs, self->parent,
646                                     self->parent_obj);
647 }
648 
PyUpb_ByNumberMap_Keys(PyObject * _self,PyObject * args)649 static PyObject* PyUpb_ByNumberMap_Keys(PyObject* _self, PyObject* args) {
650   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
651   int n = self->funcs->base.get_elem_count(self->parent);
652   PyObject* ret = PyList_New(n);
653   if (!ret) return NULL;
654   for (int i = 0; i < n; i++) {
655     const void* elem = self->funcs->base.index(self->parent, i);
656     PyObject* key = PyLong_FromLong(self->funcs->get_elem_num(elem));
657     if (!key) goto error;
658     PyList_SetItem(ret, i, key);
659   }
660   return ret;
661 
662 error:
663   Py_XDECREF(ret);
664   return NULL;
665 }
666 
PyUpb_ByNumberMap_Values(PyObject * _self,PyObject * args)667 static PyObject* PyUpb_ByNumberMap_Values(PyObject* _self, PyObject* args) {
668   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
669   int n = self->funcs->base.get_elem_count(self->parent);
670   PyObject* ret = PyList_New(n);
671   if (!ret) return NULL;
672   for (int i = 0; i < n; i++) {
673     const void* elem = self->funcs->base.index(self->parent, i);
674     PyObject* py_elem = self->funcs->base.get_elem_wrapper(elem);
675     if (!py_elem) goto error;
676     PyList_SetItem(ret, i, py_elem);
677   }
678   return ret;
679 
680 error:
681   Py_XDECREF(ret);
682   return NULL;
683 }
684 
PyUpb_ByNumberMap_Items(PyObject * _self,PyObject * args)685 static PyObject* PyUpb_ByNumberMap_Items(PyObject* _self, PyObject* args) {
686   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
687   int n = self->funcs->base.get_elem_count(self->parent);
688   PyObject* ret = PyList_New(n);
689   PyObject* item;
690   PyObject* py_elem;
691   if (!ret) return NULL;
692   for (int i = 0; i < n; i++) {
693     const void* elem = self->funcs->base.index(self->parent, i);
694     int number = self->funcs->get_elem_num(elem);
695     item = PyTuple_New(2);
696     py_elem = self->funcs->base.get_elem_wrapper(elem);
697     if (!item || !py_elem) goto error;
698     PyTuple_SetItem(item, 0, PyLong_FromLong(number));
699     PyTuple_SetItem(item, 1, py_elem);
700     PyList_SetItem(ret, i, item);
701   }
702   return ret;
703 
704 error:
705   Py_XDECREF(py_elem);
706   Py_XDECREF(item);
707   Py_XDECREF(ret);
708   return NULL;
709 }
710 
PyUpb_ByNumberMap_Contains(PyObject * _self,PyObject * key)711 static int PyUpb_ByNumberMap_Contains(PyObject* _self, PyObject* key) {
712   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
713   const void* elem = PyUpb_ByNumberMap_LookupHelper(self, key);
714   if (elem) return 1;
715   if (PyErr_Occurred()) return -1;
716   return 0;
717 }
718 
719 // A mapping container can only be equal to another mapping container, or (for
720 // backward compatibility) to a dict containing the same items.
721 // Returns 1 if equal, 0 if unequal, -1 on error.
PyUpb_ByNumberMap_IsEqual(PyUpb_ByNumberMap * self,PyObject * other)722 static int PyUpb_ByNumberMap_IsEqual(PyUpb_ByNumberMap* self, PyObject* other) {
723   // Check the identity of C++ pointers.
724   if (PyObject_TypeCheck(other, Py_TYPE(self))) {
725     PyUpb_ByNumberMap* other_map = (void*)other;
726     return self->parent == other_map->parent && self->funcs == other_map->funcs;
727   }
728 
729   if (!PyDict_Check(other)) return 0;
730 
731   PyObject* self_dict = PyDict_New();
732   PyDict_Merge(self_dict, (PyObject*)self, 0);
733   int eq = PyObject_RichCompareBool(self_dict, other, Py_EQ);
734   Py_DECREF(self_dict);
735   return eq;
736 }
737 
PyUpb_ByNumberMap_RichCompare(PyObject * _self,PyObject * other,int opid)738 static PyObject* PyUpb_ByNumberMap_RichCompare(PyObject* _self, PyObject* other,
739                                                int opid) {
740   PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
741   if (opid != Py_EQ && opid != Py_NE) {
742     Py_RETURN_NOTIMPLEMENTED;
743   }
744   bool ret = PyUpb_ByNumberMap_IsEqual(self, other);
745   if (opid == Py_NE) ret = !ret;
746   return PyBool_FromLong(ret);
747 }
748 
749 static PyMethodDef PyUpb_ByNumberMap_Methods[] = {
750     {"get", (PyCFunction)&PyUpb_ByNumberMap_Get, METH_VARARGS},
751     {"keys", PyUpb_ByNumberMap_Keys, METH_NOARGS},
752     {"values", PyUpb_ByNumberMap_Values, METH_NOARGS},
753     {"items", PyUpb_ByNumberMap_Items, METH_NOARGS},
754     {NULL}};
755 
756 static PyType_Slot PyUpb_ByNumberMap_Slots[] = {
757     {Py_mp_ass_subscript, PyUpb_ByNumberMap_AssignSubscript},
758     {Py_mp_length, PyUpb_ByNumberMap_Length},
759     {Py_mp_subscript, PyUpb_ByNumberMap_Subscript},
760     {Py_sq_contains, &PyUpb_ByNumberMap_Contains},
761     {Py_tp_dealloc, &PyUpb_ByNumberMap_Dealloc},
762     {Py_tp_iter, PyUpb_ByNumberMap_GetIter},
763     {Py_tp_methods, &PyUpb_ByNumberMap_Methods},
764     {Py_tp_repr, &PyUpb_DescriptorMap_Repr},
765     {Py_tp_richcompare, &PyUpb_ByNumberMap_RichCompare},
766     {0, NULL},
767 };
768 
769 static PyType_Spec PyUpb_ByNumberMap_Spec = {
770     PYUPB_MODULE_NAME "._ByNumberMap",  // tp_name
771     sizeof(PyUpb_ByNumberMap),          // tp_basicsize
772     0,                                  // tp_itemsize
773     Py_TPFLAGS_DEFAULT,                 // tp_flags
774     PyUpb_ByNumberMap_Slots,
775 };
776 
777 // -----------------------------------------------------------------------------
778 // Top Level
779 // -----------------------------------------------------------------------------
780 
PyUpb_InitDescriptorContainers(PyObject * m)781 bool PyUpb_InitDescriptorContainers(PyObject* m) {
782   PyUpb_ModuleState* s = PyUpb_ModuleState_GetFromModule(m);
783 
784   s->by_name_map_type = PyUpb_AddClass(m, &PyUpb_ByNameMap_Spec);
785   s->by_number_map_type = PyUpb_AddClass(m, &PyUpb_ByNumberMap_Spec);
786   s->by_name_iterator_type = PyUpb_AddClass(m, &PyUpb_ByNameIterator_Spec);
787   s->by_number_iterator_type = PyUpb_AddClass(m, &PyUpb_ByNumberIterator_Spec);
788   s->generic_sequence_type = PyUpb_AddClass(m, &PyUpb_GenericSequence_Spec);
789 
790   return s->by_name_map_type && s->by_number_map_type &&
791          s->by_name_iterator_type && s->by_number_iterator_type &&
792          s->generic_sequence_type;
793 }
794