map.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*
  2. * Copyright (c) 2009-2021, Google LLC
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of Google LLC nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
  20. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "python/map.h"
  28. #include "python/convert.h"
  29. #include "python/message.h"
  30. #include "python/protobuf.h"
  31. // -----------------------------------------------------------------------------
  32. // MapContainer
  33. // -----------------------------------------------------------------------------
  34. typedef struct {
  35. PyObject_HEAD;
  36. PyObject* arena;
  37. // The field descriptor (upb_FieldDef*).
  38. // The low bit indicates whether the container is reified (see ptr below).
  39. // - low bit set: repeated field is a stub (empty map, no underlying data).
  40. // - low bit clear: repeated field is reified (points to upb_Array).
  41. uintptr_t field;
  42. union {
  43. PyObject* parent; // stub: owning pointer to parent message.
  44. upb_Map* map; // reified: the data for this array.
  45. } ptr;
  46. int version;
  47. } PyUpb_MapContainer;
  48. static PyObject* PyUpb_MapIterator_New(PyUpb_MapContainer* map);
  49. static bool PyUpb_MapContainer_IsStub(PyUpb_MapContainer* self) {
  50. return self->field & 1;
  51. }
  52. // If the map is reified, returns it. Otherwise, returns NULL.
  53. // If NULL is returned, the object is empty and has no underlying data.
  54. static upb_Map* PyUpb_MapContainer_GetIfReified(PyUpb_MapContainer* self) {
  55. return PyUpb_MapContainer_IsStub(self) ? NULL : self->ptr.map;
  56. }
  57. static const upb_FieldDef* PyUpb_MapContainer_GetField(
  58. PyUpb_MapContainer* self) {
  59. return (const upb_FieldDef*)(self->field & ~(uintptr_t)1);
  60. }
  61. static void PyUpb_MapContainer_Dealloc(void* _self) {
  62. PyUpb_MapContainer* self = _self;
  63. Py_DECREF(self->arena);
  64. if (PyUpb_MapContainer_IsStub(self)) {
  65. PyUpb_CMessage_CacheDelete(self->ptr.parent,
  66. PyUpb_MapContainer_GetField(self));
  67. Py_DECREF(self->ptr.parent);
  68. } else {
  69. PyUpb_ObjCache_Delete(self->ptr.map);
  70. }
  71. PyUpb_Dealloc(_self);
  72. }
  73. PyTypeObject* PyUpb_MapContainer_GetClass(const upb_FieldDef* f) {
  74. assert(upb_FieldDef_IsMap(f));
  75. PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
  76. return upb_FieldDef_IsSubMessage(f) ? state->message_map_container_type
  77. : state->scalar_map_container_type;
  78. }
  79. PyObject* PyUpb_MapContainer_NewStub(PyObject* parent, const upb_FieldDef* f,
  80. PyObject* arena) {
  81. // We only create stubs when the parent is reified, by convention. However
  82. // this is not an invariant: the parent could become reified at any time.
  83. assert(PyUpb_CMessage_GetIfReified(parent) == NULL);
  84. PyTypeObject* cls = PyUpb_MapContainer_GetClass(f);
  85. PyUpb_MapContainer* map = (void*)PyType_GenericAlloc(cls, 0);
  86. map->arena = arena;
  87. map->field = (uintptr_t)f | 1;
  88. map->ptr.parent = parent;
  89. map->version = 0;
  90. Py_INCREF(arena);
  91. Py_INCREF(parent);
  92. return &map->ob_base;
  93. }
  94. void PyUpb_MapContainer_Reify(PyObject* _self, upb_Map* map) {
  95. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  96. if (!map) {
  97. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  98. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  99. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  100. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  101. const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
  102. map = upb_Map_New(arena, upb_FieldDef_CType(key_f),
  103. upb_FieldDef_CType(val_f));
  104. }
  105. PyUpb_ObjCache_Add(map, &self->ob_base);
  106. Py_DECREF(self->ptr.parent);
  107. self->ptr.map = map; // Overwrites self->ptr.parent.
  108. self->field &= ~(uintptr_t)1;
  109. assert(!PyUpb_MapContainer_IsStub(self));
  110. }
  111. void PyUpb_MapContainer_Invalidate(PyObject* obj) {
  112. PyUpb_MapContainer* self = (PyUpb_MapContainer*)obj;
  113. self->version++;
  114. }
  115. upb_Map* PyUpb_MapContainer_EnsureReified(PyObject* _self) {
  116. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  117. self->version++;
  118. upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
  119. if (map) return map; // Already writable.
  120. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  121. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  122. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  123. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  124. const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
  125. map =
  126. upb_Map_New(arena, upb_FieldDef_CType(key_f), upb_FieldDef_CType(val_f));
  127. upb_MessageValue msgval = {.map_val = map};
  128. PyUpb_CMessage_SetConcreteSubobj(self->ptr.parent, f, msgval);
  129. PyUpb_MapContainer_Reify((PyObject*)self, map);
  130. return map;
  131. }
  132. int PyUpb_MapContainer_AssignSubscript(PyObject* _self, PyObject* key,
  133. PyObject* val) {
  134. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  135. upb_Map* map = PyUpb_MapContainer_EnsureReified(_self);
  136. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  137. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  138. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  139. const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
  140. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  141. upb_MessageValue u_key, u_val;
  142. if (!PyUpb_PyToUpb(key, key_f, &u_key, arena)) return -1;
  143. if (val) {
  144. if (!PyUpb_PyToUpb(val, val_f, &u_val, arena)) return -1;
  145. upb_Map_Set(map, u_key, u_val, arena);
  146. } else {
  147. if (!upb_Map_Delete(map, u_key)) {
  148. PyErr_Format(PyExc_KeyError, "Key not present in map");
  149. return -1;
  150. }
  151. }
  152. return 0;
  153. }
  154. PyObject* PyUpb_MapContainer_Subscript(PyObject* _self, PyObject* key) {
  155. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  156. upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
  157. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  158. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  159. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  160. const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
  161. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  162. upb_MessageValue u_key, u_val;
  163. if (!PyUpb_PyToUpb(key, key_f, &u_key, arena)) return NULL;
  164. if (!map || !upb_Map_Get(map, u_key, &u_val)) {
  165. map = PyUpb_MapContainer_EnsureReified(_self);
  166. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  167. if (upb_FieldDef_IsSubMessage(val_f)) {
  168. u_val.msg_val = upb_Message_New(upb_FieldDef_MessageSubDef(val_f), arena);
  169. } else {
  170. memset(&u_val, 0, sizeof(u_val));
  171. }
  172. upb_Map_Set(map, u_key, u_val, arena);
  173. }
  174. return PyUpb_UpbToPy(u_val, val_f, self->arena);
  175. }
  176. PyObject* PyUpb_MapContainer_Contains(PyObject* _self, PyObject* key) {
  177. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  178. upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
  179. if (!map) Py_RETURN_FALSE;
  180. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  181. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  182. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  183. upb_MessageValue u_key;
  184. if (!PyUpb_PyToUpb(key, key_f, &u_key, NULL)) return NULL;
  185. if (upb_Map_Get(map, u_key, NULL)) {
  186. Py_RETURN_TRUE;
  187. } else {
  188. Py_RETURN_FALSE;
  189. }
  190. }
  191. PyObject* PyUpb_MapContainer_Clear(PyObject* _self, PyObject* key) {
  192. upb_Map* map = PyUpb_MapContainer_EnsureReified(_self);
  193. upb_Map_Clear(map);
  194. Py_RETURN_NONE;
  195. }
  196. static PyObject* PyUpb_MapContainer_Get(PyObject* _self, PyObject* args,
  197. PyObject* kwargs) {
  198. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  199. static const char* kwlist[] = {"key", "default", NULL};
  200. PyObject* key;
  201. PyObject* default_value = NULL;
  202. upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
  203. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", (char**)kwlist, &key,
  204. &default_value)) {
  205. return NULL;
  206. }
  207. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  208. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  209. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  210. const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
  211. upb_Arena* arena = PyUpb_Arena_Get(self->arena);
  212. upb_MessageValue u_key, u_val;
  213. if (!PyUpb_PyToUpb(key, key_f, &u_key, arena)) return NULL;
  214. if (map && upb_Map_Get(map, u_key, &u_val)) {
  215. return PyUpb_UpbToPy(u_val, val_f, self->arena);
  216. }
  217. if (default_value) {
  218. Py_INCREF(default_value);
  219. return default_value;
  220. }
  221. Py_RETURN_NONE;
  222. }
  223. static PyObject* PyUpb_MapContainer_GetEntryClass(PyObject* _self,
  224. PyObject* arg) {
  225. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  226. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  227. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  228. return PyUpb_Descriptor_GetClass(entry_m);
  229. }
  230. Py_ssize_t PyUpb_MapContainer_Length(PyObject* _self) {
  231. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  232. upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
  233. return map ? upb_Map_Size(map) : 0;
  234. }
  235. PyUpb_MapContainer* PyUpb_MapContainer_Check(PyObject* _self) {
  236. PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
  237. if (!PyObject_TypeCheck(_self, state->message_map_container_type) &&
  238. !PyObject_TypeCheck(_self, state->scalar_map_container_type)) {
  239. PyErr_Format(PyExc_TypeError, "Expected protobuf map, but got %R", _self);
  240. return NULL;
  241. }
  242. return (PyUpb_MapContainer*)_self;
  243. }
  244. int PyUpb_CMessage_InitMapAttributes(PyObject* map, PyObject* value,
  245. const upb_FieldDef* f);
  246. static PyObject* PyUpb_MapContainer_MergeFrom(PyObject* _self, PyObject* _arg) {
  247. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  248. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  249. if (PyDict_Check(_arg)) {
  250. return PyErr_Format(PyExc_AttributeError, "Merging of dict is not allowed");
  251. }
  252. if (PyUpb_CMessage_InitMapAttributes(_self, _arg, f) < 0) {
  253. return NULL;
  254. }
  255. Py_RETURN_NONE;
  256. }
  257. static PyObject* PyUpb_MapContainer_Repr(PyObject* _self) {
  258. PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
  259. upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
  260. PyObject* dict = PyDict_New();
  261. if (map) {
  262. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
  263. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  264. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  265. const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
  266. size_t iter = kUpb_Map_Begin;
  267. while (upb_MapIterator_Next(map, &iter)) {
  268. PyObject* key =
  269. PyUpb_UpbToPy(upb_MapIterator_Key(map, iter), key_f, self->arena);
  270. PyObject* val =
  271. PyUpb_UpbToPy(upb_MapIterator_Value(map, iter), val_f, self->arena);
  272. if (!key || !val) {
  273. Py_XDECREF(key);
  274. Py_XDECREF(val);
  275. Py_DECREF(dict);
  276. return NULL;
  277. }
  278. PyDict_SetItem(dict, key, val);
  279. Py_DECREF(key);
  280. Py_DECREF(val);
  281. }
  282. }
  283. PyObject* repr = PyObject_Repr(dict);
  284. Py_DECREF(dict);
  285. return repr;
  286. }
  287. PyObject* PyUpb_MapContainer_GetOrCreateWrapper(upb_Map* map,
  288. const upb_FieldDef* f,
  289. PyObject* arena) {
  290. PyUpb_MapContainer* ret = (void*)PyUpb_ObjCache_Get(map);
  291. if (ret) return &ret->ob_base;
  292. PyTypeObject* cls = PyUpb_MapContainer_GetClass(f);
  293. ret = (void*)PyType_GenericAlloc(cls, 0);
  294. ret->arena = arena;
  295. ret->field = (uintptr_t)f;
  296. ret->ptr.map = map;
  297. ret->version = 0;
  298. Py_INCREF(arena);
  299. PyUpb_ObjCache_Add(map, &ret->ob_base);
  300. return &ret->ob_base;
  301. }
  302. // -----------------------------------------------------------------------------
  303. // ScalarMapContainer
  304. // -----------------------------------------------------------------------------
  305. static PyMethodDef PyUpb_ScalarMapContainer_Methods[] = {
  306. {"__contains__", PyUpb_MapContainer_Contains, METH_O,
  307. "Tests whether a key is a member of the map."},
  308. {"clear", PyUpb_MapContainer_Clear, METH_NOARGS,
  309. "Removes all elements from the map."},
  310. {"get", (PyCFunction)PyUpb_MapContainer_Get, METH_VARARGS | METH_KEYWORDS,
  311. "Gets the value for the given key if present, or otherwise a default"},
  312. {"GetEntryClass", PyUpb_MapContainer_GetEntryClass, METH_NOARGS,
  313. "Return the class used to build Entries of (key, value) pairs."},
  314. {"MergeFrom", PyUpb_MapContainer_MergeFrom, METH_O,
  315. "Merges a map into the current map."},
  316. /*
  317. { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
  318. "Makes a deep copy of the class." },
  319. { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
  320. "Outputs picklable representation of the repeated field." },
  321. */
  322. {NULL, NULL},
  323. };
  324. static PyType_Slot PyUpb_ScalarMapContainer_Slots[] = {
  325. {Py_tp_dealloc, PyUpb_MapContainer_Dealloc},
  326. {Py_mp_length, PyUpb_MapContainer_Length},
  327. {Py_mp_subscript, PyUpb_MapContainer_Subscript},
  328. {Py_mp_ass_subscript, PyUpb_MapContainer_AssignSubscript},
  329. {Py_tp_methods, PyUpb_ScalarMapContainer_Methods},
  330. {Py_tp_iter, PyUpb_MapIterator_New},
  331. {Py_tp_repr, PyUpb_MapContainer_Repr},
  332. {Py_tp_hash, PyObject_HashNotImplemented},
  333. {0, NULL},
  334. };
  335. static PyType_Spec PyUpb_ScalarMapContainer_Spec = {
  336. PYUPB_MODULE_NAME ".ScalarMapContainer",
  337. sizeof(PyUpb_MapContainer),
  338. 0,
  339. Py_TPFLAGS_DEFAULT,
  340. PyUpb_ScalarMapContainer_Slots,
  341. };
  342. // -----------------------------------------------------------------------------
  343. // MessageMapContainer
  344. // -----------------------------------------------------------------------------
  345. static PyMethodDef PyUpb_MessageMapContainer_Methods[] = {
  346. {"__contains__", PyUpb_MapContainer_Contains, METH_O,
  347. "Tests whether the map contains this element."},
  348. {"clear", PyUpb_MapContainer_Clear, METH_NOARGS,
  349. "Removes all elements from the map."},
  350. {"get", (PyCFunction)PyUpb_MapContainer_Get, METH_VARARGS | METH_KEYWORDS,
  351. "Gets the value for the given key if present, or otherwise a default"},
  352. {"get_or_create", PyUpb_MapContainer_Subscript, METH_O,
  353. "Alias for getitem, useful to make explicit that the map is mutated."},
  354. {"GetEntryClass", PyUpb_MapContainer_GetEntryClass, METH_NOARGS,
  355. "Return the class used to build Entries of (key, value) pairs."},
  356. {"MergeFrom", PyUpb_MapContainer_MergeFrom, METH_O,
  357. "Merges a map into the current map."},
  358. /*
  359. { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
  360. "Makes a deep copy of the class." },
  361. { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
  362. "Outputs picklable representation of the repeated field." },
  363. */
  364. {NULL, NULL},
  365. };
  366. static PyType_Slot PyUpb_MessageMapContainer_Slots[] = {
  367. {Py_tp_dealloc, PyUpb_MapContainer_Dealloc},
  368. {Py_mp_length, PyUpb_MapContainer_Length},
  369. {Py_mp_subscript, PyUpb_MapContainer_Subscript},
  370. {Py_mp_ass_subscript, PyUpb_MapContainer_AssignSubscript},
  371. {Py_tp_methods, PyUpb_MessageMapContainer_Methods},
  372. {Py_tp_iter, PyUpb_MapIterator_New},
  373. {Py_tp_repr, PyUpb_MapContainer_Repr},
  374. {Py_tp_hash, PyObject_HashNotImplemented},
  375. {0, NULL}};
  376. static PyType_Spec PyUpb_MessageMapContainer_Spec = {
  377. PYUPB_MODULE_NAME ".MessageMapContainer", sizeof(PyUpb_MapContainer), 0,
  378. Py_TPFLAGS_DEFAULT, PyUpb_MessageMapContainer_Slots};
  379. // -----------------------------------------------------------------------------
  380. // MapIterator
  381. // -----------------------------------------------------------------------------
  382. typedef struct {
  383. PyObject_HEAD;
  384. PyUpb_MapContainer* map; // We own a reference.
  385. size_t iter;
  386. int version;
  387. } PyUpb_MapIterator;
  388. static PyObject* PyUpb_MapIterator_New(PyUpb_MapContainer* map) {
  389. PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
  390. PyUpb_MapIterator* iter =
  391. (void*)PyType_GenericAlloc(state->map_iterator_type, 0);
  392. iter->map = map;
  393. iter->iter = kUpb_Map_Begin;
  394. iter->version = map->version;
  395. Py_INCREF(map);
  396. return &iter->ob_base;
  397. }
  398. static void PyUpb_MapIterator_Dealloc(void* _self) {
  399. PyUpb_MapIterator* self = (PyUpb_MapIterator*)_self;
  400. Py_DECREF(&self->map->ob_base);
  401. PyUpb_Dealloc(_self);
  402. }
  403. PyObject* PyUpb_MapIterator_IterNext(PyObject* _self) {
  404. PyUpb_MapIterator* self = (PyUpb_MapIterator*)_self;
  405. if (self->version != self->map->version) {
  406. return PyErr_Format(PyExc_RuntimeError, "Map modified during iteration.");
  407. }
  408. upb_Map* map = PyUpb_MapContainer_GetIfReified(self->map);
  409. if (!map) return NULL;
  410. if (!upb_MapIterator_Next(map, &self->iter)) return NULL;
  411. upb_MessageValue key = upb_MapIterator_Key(map, self->iter);
  412. const upb_FieldDef* f = PyUpb_MapContainer_GetField(self->map);
  413. const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
  414. const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
  415. return PyUpb_UpbToPy(key, key_f, self->map->arena);
  416. }
  417. static PyType_Slot PyUpb_MapIterator_Slots[] = {
  418. {Py_tp_dealloc, PyUpb_MapIterator_Dealloc},
  419. {Py_tp_iter, PyObject_SelfIter},
  420. {Py_tp_iternext, PyUpb_MapIterator_IterNext},
  421. {0, NULL}};
  422. static PyType_Spec PyUpb_MapIterator_Spec = {
  423. PYUPB_MODULE_NAME ".MapIterator", sizeof(PyUpb_MapIterator), 0,
  424. Py_TPFLAGS_DEFAULT, PyUpb_MapIterator_Slots};
  425. // -----------------------------------------------------------------------------
  426. // Top Level
  427. // -----------------------------------------------------------------------------
  428. static PyObject* GetMutableMappingBase(void) {
  429. PyObject* collections = NULL;
  430. PyObject* mapping = NULL;
  431. PyObject* bases = NULL;
  432. if ((collections = PyImport_ImportModule("collections.abc")) &&
  433. (mapping = PyObject_GetAttrString(collections, "MutableMapping"))) {
  434. bases = Py_BuildValue("(O)", mapping);
  435. }
  436. Py_XDECREF(collections);
  437. Py_XDECREF(mapping);
  438. return bases;
  439. }
  440. bool PyUpb_Map_Init(PyObject* m) {
  441. PyUpb_ModuleState* state = PyUpb_ModuleState_GetFromModule(m);
  442. PyObject* bases = GetMutableMappingBase();
  443. if (!bases) return false;
  444. state->message_map_container_type =
  445. PyUpb_AddClassWithBases(m, &PyUpb_MessageMapContainer_Spec, bases);
  446. state->scalar_map_container_type =
  447. PyUpb_AddClassWithBases(m, &PyUpb_ScalarMapContainer_Spec, bases);
  448. state->map_iterator_type = PyUpb_AddClass(m, &PyUpb_MapIterator_Spec);
  449. Py_DECREF(bases);
  450. return state->message_map_container_type &&
  451. state->scalar_map_container_type && state->map_iterator_type;
  452. }