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