// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

#include "python/descriptor_containers.h"

#include "python/descriptor.h"
#include "python/protobuf.h"
#include "upb/reflection/def.h"

// Implements __repr__ as str(dict(self)).
static PyObject* PyUpb_DescriptorMap_Repr(PyObject* _self) {
  PyObject* dict = PyDict_New();
  PyObject* ret = NULL;
  if (!dict) goto err;
  if (PyDict_Merge(dict, _self, 1) != 0) goto err;
  ret = PyObject_Str(dict);

err:
  Py_XDECREF(dict);
  return ret;
}

#define CHECK_TYPE(obj, state_member)                                   \
  assert(PyUpb_ModuleState_MaybeGet() == NULL || /* During shutdown. */ \
         Py_TYPE(obj) == PyUpb_ModuleState_Get()->state_member)

// -----------------------------------------------------------------------------
// ByNameIterator
// -----------------------------------------------------------------------------

typedef struct {
  // clang-format off
  PyObject_HEAD
  const PyUpb_ByNameMap_Funcs* funcs;
  // clang-format on
  const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
  PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
  int index;             // Current iterator index.
} PyUpb_ByNameIterator;

static PyUpb_ByNameIterator* PyUpb_ByNameIterator_Self(PyObject* obj) {
  CHECK_TYPE(obj, by_name_iterator_type);
  return (PyUpb_ByNameIterator*)obj;
}

static void PyUpb_ByNameIterator_Dealloc(PyObject* _self) {
  PyUpb_ByNameIterator* self = PyUpb_ByNameIterator_Self(_self);
  Py_DECREF(self->parent_obj);
  PyUpb_Dealloc(self);
}

static PyObject* PyUpb_ByNameIterator_New(const PyUpb_ByNameMap_Funcs* funcs,
                                          const void* parent,
                                          PyObject* parent_obj) {
  PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
  PyUpb_ByNameIterator* iter =
      (void*)PyType_GenericAlloc(s->by_name_iterator_type, 0);
  iter->funcs = funcs;
  iter->parent = parent;
  iter->parent_obj = parent_obj;
  iter->index = 0;
  Py_INCREF(iter->parent_obj);
  return &iter->ob_base;
}

static PyObject* PyUpb_ByNameIterator_IterNext(PyObject* _self) {
  PyUpb_ByNameIterator* self = PyUpb_ByNameIterator_Self(_self);
  int size = self->funcs->base.get_elem_count(self->parent);
  if (self->index >= size) return NULL;
  const void* elem = self->funcs->base.index(self->parent, self->index);
  self->index++;
  return PyUnicode_FromString(self->funcs->get_elem_name(elem));
}

static PyType_Slot PyUpb_ByNameIterator_Slots[] = {
    {Py_tp_dealloc, PyUpb_ByNameIterator_Dealloc},
    {Py_tp_iter, PyObject_SelfIter},
    {Py_tp_iternext, PyUpb_ByNameIterator_IterNext},
    {0, NULL}};

static PyType_Spec PyUpb_ByNameIterator_Spec = {
    PYUPB_MODULE_NAME "._ByNameIterator",  // tp_name
    sizeof(PyUpb_ByNameIterator),          // tp_basicsize
    0,                                     // tp_itemsize
    Py_TPFLAGS_DEFAULT,                    // tp_flags
    PyUpb_ByNameIterator_Slots,
};

// -----------------------------------------------------------------------------
// ByNumberIterator
// -----------------------------------------------------------------------------

typedef struct {
  // clang-format off
  PyObject_HEAD
  const PyUpb_ByNumberMap_Funcs* funcs;
  // clang-format on
  const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
  PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
  int index;             // Current iterator index.
} PyUpb_ByNumberIterator;

static PyUpb_ByNumberIterator* PyUpb_ByNumberIterator_Self(PyObject* obj) {
  CHECK_TYPE(obj, by_number_iterator_type);
  return (PyUpb_ByNumberIterator*)obj;
}

static void PyUpb_ByNumberIterator_Dealloc(PyObject* _self) {
  PyUpb_ByNumberIterator* self = PyUpb_ByNumberIterator_Self(_self);
  Py_DECREF(self->parent_obj);
  PyUpb_Dealloc(self);
}

static PyObject* PyUpb_ByNumberIterator_New(
    const PyUpb_ByNumberMap_Funcs* funcs, const void* parent,
    PyObject* parent_obj) {
  PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
  PyUpb_ByNumberIterator* iter =
      (void*)PyType_GenericAlloc(s->by_number_iterator_type, 0);
  iter->funcs = funcs;
  iter->parent = parent;
  iter->parent_obj = parent_obj;
  iter->index = 0;
  Py_INCREF(iter->parent_obj);
  return &iter->ob_base;
}

static PyObject* PyUpb_ByNumberIterator_IterNext(PyObject* _self) {
  PyUpb_ByNumberIterator* self = PyUpb_ByNumberIterator_Self(_self);
  int size = self->funcs->base.get_elem_count(self->parent);
  if (self->index >= size) return NULL;
  const void* elem = self->funcs->base.index(self->parent, self->index);
  self->index++;
  return PyLong_FromLong(self->funcs->get_elem_num(elem));
}

static PyType_Slot PyUpb_ByNumberIterator_Slots[] = {
    {Py_tp_dealloc, PyUpb_ByNumberIterator_Dealloc},
    {Py_tp_iter, PyObject_SelfIter},
    {Py_tp_iternext, PyUpb_ByNumberIterator_IterNext},
    {0, NULL}};

static PyType_Spec PyUpb_ByNumberIterator_Spec = {
    PYUPB_MODULE_NAME "._ByNumberIterator",  // tp_name
    sizeof(PyUpb_ByNumberIterator),          // tp_basicsize
    0,                                       // tp_itemsize
    Py_TPFLAGS_DEFAULT,                      // tp_flags
    PyUpb_ByNumberIterator_Slots,
};

// -----------------------------------------------------------------------------
// GenericSequence
// -----------------------------------------------------------------------------

typedef struct {
  // clang-format off
  PyObject_HEAD
  const PyUpb_GenericSequence_Funcs* funcs;
  // clang-format on
  const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
  PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
} PyUpb_GenericSequence;

PyUpb_GenericSequence* PyUpb_GenericSequence_Self(PyObject* obj) {
  CHECK_TYPE(obj, generic_sequence_type);
  return (PyUpb_GenericSequence*)obj;
}

static void PyUpb_GenericSequence_Dealloc(PyObject* _self) {
  PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
  Py_CLEAR(self->parent_obj);
  PyUpb_Dealloc(self);
}

PyObject* PyUpb_GenericSequence_New(const PyUpb_GenericSequence_Funcs* funcs,
                                    const void* parent, PyObject* parent_obj) {
  PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
  PyUpb_GenericSequence* seq =
      (PyUpb_GenericSequence*)PyType_GenericAlloc(s->generic_sequence_type, 0);
  seq->funcs = funcs;
  seq->parent = parent;
  seq->parent_obj = parent_obj;
  Py_INCREF(parent_obj);
  return &seq->ob_base;
}

static Py_ssize_t PyUpb_GenericSequence_Length(PyObject* _self) {
  PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
  return self->funcs->get_elem_count(self->parent);
}

static PyObject* PyUpb_GenericSequence_GetItem(PyObject* _self,
                                               Py_ssize_t index) {
  PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
  Py_ssize_t size = self->funcs->get_elem_count(self->parent);
  if (index < 0) {
    index += size;
  }
  if (index < 0 || index >= size) {
    PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
    return NULL;
  }
  const void* elem = self->funcs->index(self->parent, index);
  return self->funcs->get_elem_wrapper(elem);
}

// A sequence container can only be equal to another sequence container, or (for
// backward compatibility) to a list containing the same items.
// Returns 1 if equal, 0 if unequal, -1 on error.
static int PyUpb_GenericSequence_IsEqual(PyUpb_GenericSequence* self,
                                         PyObject* other) {
  // Check the identity of C++ pointers.
  if (PyObject_TypeCheck(other, Py_TYPE(self))) {
    PyUpb_GenericSequence* other_seq = (void*)other;
    return self->parent == other_seq->parent && self->funcs == other_seq->funcs;
  }

  if (!PyList_Check(other)) return 0;

  // return list(self) == other
  // We can clamp `i` to int because GenericSequence uses int for size (this
  // is useful when we do int iteration below).
  int n = PyUpb_GenericSequence_Length((PyObject*)self);
  if ((Py_ssize_t)n != PyList_Size(other)) {
    return false;
  }

  PyObject* item1;
  for (int i = 0; i < n; i++) {
    item1 = PyUpb_GenericSequence_GetItem((PyObject*)self, i);
    PyObject* item2 = PyList_GetItem(other, i);
    if (!item1 || !item2) goto error;
    int cmp = PyObject_RichCompareBool(item1, item2, Py_EQ);
    Py_DECREF(item1);
    if (cmp != 1) return cmp;
  }
  // All items were found and equal
  return 1;

error:
  Py_XDECREF(item1);
  return -1;
}

static PyObject* PyUpb_GenericSequence_RichCompare(PyObject* _self,
                                                   PyObject* other, int opid) {
  PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
  if (opid != Py_EQ && opid != Py_NE) {
    Py_RETURN_NOTIMPLEMENTED;
  }
  bool ret = PyUpb_GenericSequence_IsEqual(self, other);
  if (opid == Py_NE) ret = !ret;
  return PyBool_FromLong(ret);
}

static PyObject* PyUpb_GenericSequence_Subscript(PyObject* _self,
                                                 PyObject* item) {
  PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
  Py_ssize_t size = self->funcs->get_elem_count(self->parent);
  Py_ssize_t idx, count, step;
  if (!PyUpb_IndexToRange(item, size, &idx, &count, &step)) return NULL;
  if (step == 0) {
    return PyUpb_GenericSequence_GetItem(_self, idx);
  } else {
    PyObject* list = PyList_New(count);
    for (Py_ssize_t i = 0; i < count; i++, idx += step) {
      const void* elem = self->funcs->index(self->parent, idx);
      PyList_SetItem(list, i, self->funcs->get_elem_wrapper(elem));
    }
    return list;
  }
}

// Linear search.  Could optimize this in some cases (defs that have index),
// but not all (FileDescriptor.dependencies).
static int PyUpb_GenericSequence_Find(PyObject* _self, PyObject* item) {
  PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
  const void* item_ptr = PyUpb_AnyDescriptor_GetDef(item);
  int count = self->funcs->get_elem_count(self->parent);
  for (int i = 0; i < count; i++) {
    if (self->funcs->index(self->parent, i) == item_ptr) {
      return i;
    }
  }
  return -1;
}

static PyObject* PyUpb_GenericSequence_Index(PyObject* self, PyObject* item) {
  int position = PyUpb_GenericSequence_Find(self, item);
  if (position < 0) {
    PyErr_SetNone(PyExc_ValueError);
    return NULL;
  } else {
    return PyLong_FromLong(position);
  }
}

static PyObject* PyUpb_GenericSequence_Count(PyObject* _self, PyObject* item) {
  PyUpb_GenericSequence* self = PyUpb_GenericSequence_Self(_self);
  const void* item_ptr = PyUpb_AnyDescriptor_GetDef(item);
  int n = self->funcs->get_elem_count(self->parent);
  int count = 0;
  for (int i = 0; i < n; i++) {
    if (self->funcs->index(self->parent, i) == item_ptr) {
      count++;
    }
  }
  return PyLong_FromLong(count);
}

static PyObject* PyUpb_GenericSequence_Append(PyObject* self, PyObject* args) {
  PyErr_Format(PyExc_TypeError, "'%R' is not a mutable sequence", self);
  return NULL;
}

static PyMethodDef PyUpb_GenericSequence_Methods[] = {
    {"index", PyUpb_GenericSequence_Index, METH_O},
    {"count", PyUpb_GenericSequence_Count, METH_O},
    {"append", PyUpb_GenericSequence_Append, METH_O},
    // This was implemented for Python/C++ but so far has not been required.
    //{ "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
    {NULL}};

static PyType_Slot PyUpb_GenericSequence_Slots[] = {
    {Py_tp_dealloc, &PyUpb_GenericSequence_Dealloc},
    {Py_tp_methods, &PyUpb_GenericSequence_Methods},
    {Py_sq_length, PyUpb_GenericSequence_Length},
    {Py_sq_item, PyUpb_GenericSequence_GetItem},
    {Py_tp_richcompare, &PyUpb_GenericSequence_RichCompare},
    {Py_mp_subscript, PyUpb_GenericSequence_Subscript},
    // These were implemented for Python/C++ but so far have not been required.
    // {Py_tp_repr, &PyUpb_GenericSequence_Repr},
    // {Py_sq_contains, PyUpb_GenericSequence_Contains},
    // {Py_mp_ass_subscript, PyUpb_GenericSequence_AssignSubscript},
    {0, NULL},
};

static PyType_Spec PyUpb_GenericSequence_Spec = {
    PYUPB_MODULE_NAME "._GenericSequence",  // tp_name
    sizeof(PyUpb_GenericSequence),          // tp_basicsize
    0,                                      // tp_itemsize
    Py_TPFLAGS_DEFAULT,                     // tp_flags
    PyUpb_GenericSequence_Slots,
};

// -----------------------------------------------------------------------------
// ByNameMap
// -----------------------------------------------------------------------------

typedef struct {
  // clang-format off
  PyObject_HEAD
  const PyUpb_ByNameMap_Funcs* funcs;
  // clang-format on
  const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
  PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
} PyUpb_ByNameMap;

PyUpb_ByNameMap* PyUpb_ByNameMap_Self(PyObject* obj) {
  CHECK_TYPE(obj, by_name_map_type);
  return (PyUpb_ByNameMap*)obj;
}

static void PyUpb_ByNameMap_Dealloc(PyObject* _self) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  Py_DECREF(self->parent_obj);
  PyUpb_Dealloc(self);
}

PyObject* PyUpb_ByNameMap_New(const PyUpb_ByNameMap_Funcs* funcs,
                              const void* parent, PyObject* parent_obj) {
  PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
  PyUpb_ByNameMap* map = (void*)PyType_GenericAlloc(s->by_name_map_type, 0);
  map->funcs = funcs;
  map->parent = parent;
  map->parent_obj = parent_obj;
  Py_INCREF(parent_obj);
  return &map->ob_base;
}

static Py_ssize_t PyUpb_ByNameMap_Length(PyObject* _self) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  return self->funcs->base.get_elem_count(self->parent);
}

static PyObject* PyUpb_ByNameMap_Subscript(PyObject* _self, PyObject* key) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  const char* name = PyUpb_GetStrData(key);
  const void* elem = name ? self->funcs->lookup(self->parent, name) : NULL;

  if (!name && PyObject_Hash(key) == -1) return NULL;

  if (elem) {
    return self->funcs->base.get_elem_wrapper(elem);
  } else {
    PyErr_SetObject(PyExc_KeyError, key);
    return NULL;
  }
}

static int PyUpb_ByNameMap_AssignSubscript(PyObject* self, PyObject* key,
                                           PyObject* value) {
  PyErr_Format(PyExc_TypeError, PYUPB_MODULE_NAME
               ".ByNameMap' object does not support item assignment");
  return -1;
}

static int PyUpb_ByNameMap_Contains(PyObject* _self, PyObject* key) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  const char* name = PyUpb_GetStrData(key);
  const void* elem = name ? self->funcs->lookup(self->parent, name) : NULL;
  if (!name && PyObject_Hash(key) == -1) return -1;
  return elem ? 1 : 0;
}

static PyObject* PyUpb_ByNameMap_Get(PyObject* _self, PyObject* args) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  PyObject* key;
  PyObject* default_value = Py_None;
  if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
    return NULL;
  }

  const char* name = PyUpb_GetStrData(key);
  const void* elem = name ? self->funcs->lookup(self->parent, name) : NULL;

  if (!name && PyObject_Hash(key) == -1) return NULL;

  if (elem) {
    return self->funcs->base.get_elem_wrapper(elem);
  } else {
    Py_INCREF(default_value);
    return default_value;
  }
}

static PyObject* PyUpb_ByNameMap_GetIter(PyObject* _self) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  return PyUpb_ByNameIterator_New(self->funcs, self->parent, self->parent_obj);
}

static PyObject* PyUpb_ByNameMap_Keys(PyObject* _self, PyObject* args) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  int n = self->funcs->base.get_elem_count(self->parent);
  PyObject* ret = PyList_New(n);
  if (!ret) return NULL;
  for (int i = 0; i < n; i++) {
    const void* elem = self->funcs->base.index(self->parent, i);
    PyObject* key = PyUnicode_FromString(self->funcs->get_elem_name(elem));
    if (!key) goto error;
    PyList_SetItem(ret, i, key);
  }
  return ret;

error:
  Py_XDECREF(ret);
  return NULL;
}

static PyObject* PyUpb_ByNameMap_Values(PyObject* _self, PyObject* args) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  int n = self->funcs->base.get_elem_count(self->parent);
  PyObject* ret = PyList_New(n);
  if (!ret) return NULL;
  for (int i = 0; i < n; i++) {
    const void* elem = self->funcs->base.index(self->parent, i);
    PyObject* py_elem = self->funcs->base.get_elem_wrapper(elem);
    if (!py_elem) goto error;
    PyList_SetItem(ret, i, py_elem);
  }
  return ret;

error:
  Py_XDECREF(ret);
  return NULL;
}

static PyObject* PyUpb_ByNameMap_Items(PyObject* _self, PyObject* args) {
  PyUpb_ByNameMap* self = (PyUpb_ByNameMap*)_self;
  int n = self->funcs->base.get_elem_count(self->parent);
  PyObject* ret = PyList_New(n);
  PyObject* item;
  PyObject* py_elem;
  if (!ret) return NULL;
  for (int i = 0; i < n; i++) {
    const void* elem = self->funcs->base.index(self->parent, i);
    item = PyTuple_New(2);
    py_elem = self->funcs->base.get_elem_wrapper(elem);
    if (!item || !py_elem) goto error;
    PyTuple_SetItem(item, 0,
                    PyUnicode_FromString(self->funcs->get_elem_name(elem)));
    PyTuple_SetItem(item, 1, py_elem);
    PyList_SetItem(ret, i, item);
  }
  return ret;

error:
  Py_XDECREF(py_elem);
  Py_XDECREF(item);
  Py_XDECREF(ret);
  return NULL;
}

// A mapping container can only be equal to another mapping container, or (for
// backward compatibility) to a dict containing the same items.
// Returns 1 if equal, 0 if unequal, -1 on error.
static int PyUpb_ByNameMap_IsEqual(PyUpb_ByNameMap* self, PyObject* other) {
  // Check the identity of C++ pointers.
  if (PyObject_TypeCheck(other, Py_TYPE(self))) {
    PyUpb_ByNameMap* other_map = (void*)other;
    return self->parent == other_map->parent && self->funcs == other_map->funcs;
  }

  if (!PyDict_Check(other)) return 0;

  PyObject* self_dict = PyDict_New();
  PyDict_Merge(self_dict, (PyObject*)self, 0);
  int eq = PyObject_RichCompareBool(self_dict, other, Py_EQ);
  Py_DECREF(self_dict);
  return eq;
}

static PyObject* PyUpb_ByNameMap_RichCompare(PyObject* _self, PyObject* other,
                                             int opid) {
  PyUpb_ByNameMap* self = PyUpb_ByNameMap_Self(_self);
  if (opid != Py_EQ && opid != Py_NE) {
    Py_RETURN_NOTIMPLEMENTED;
  }
  bool ret = PyUpb_ByNameMap_IsEqual(self, other);
  if (opid == Py_NE) ret = !ret;
  return PyBool_FromLong(ret);
}

static PyMethodDef PyUpb_ByNameMap_Methods[] = {
    {"get", (PyCFunction)&PyUpb_ByNameMap_Get, METH_VARARGS},
    {"keys", PyUpb_ByNameMap_Keys, METH_NOARGS},
    {"values", PyUpb_ByNameMap_Values, METH_NOARGS},
    {"items", PyUpb_ByNameMap_Items, METH_NOARGS},
    {NULL}};

static PyType_Slot PyUpb_ByNameMap_Slots[] = {
    {Py_mp_ass_subscript, PyUpb_ByNameMap_AssignSubscript},
    {Py_mp_length, PyUpb_ByNameMap_Length},
    {Py_mp_subscript, PyUpb_ByNameMap_Subscript},
    {Py_sq_contains, &PyUpb_ByNameMap_Contains},
    {Py_tp_dealloc, &PyUpb_ByNameMap_Dealloc},
    {Py_tp_iter, PyUpb_ByNameMap_GetIter},
    {Py_tp_methods, &PyUpb_ByNameMap_Methods},
    {Py_tp_repr, &PyUpb_DescriptorMap_Repr},
    {Py_tp_richcompare, &PyUpb_ByNameMap_RichCompare},
    {0, NULL},
};

static PyType_Spec PyUpb_ByNameMap_Spec = {
    PYUPB_MODULE_NAME "._ByNameMap",  // tp_name
    sizeof(PyUpb_ByNameMap),          // tp_basicsize
    0,                                // tp_itemsize
    Py_TPFLAGS_DEFAULT,               // tp_flags
    PyUpb_ByNameMap_Slots,
};

// -----------------------------------------------------------------------------
// ByNumberMap
// -----------------------------------------------------------------------------

typedef struct {
  // clang-format off
  PyObject_HEAD
  const PyUpb_ByNumberMap_Funcs* funcs;
  // clang-format on
  const void* parent;    // upb_MessageDef*, upb_DefPool*, etc.
  PyObject* parent_obj;  // Python object that keeps parent alive, we own a ref.
} PyUpb_ByNumberMap;

PyUpb_ByNumberMap* PyUpb_ByNumberMap_Self(PyObject* obj) {
  CHECK_TYPE(obj, by_number_map_type);
  return (PyUpb_ByNumberMap*)obj;
}

PyObject* PyUpb_ByNumberMap_New(const PyUpb_ByNumberMap_Funcs* funcs,
                                const void* parent, PyObject* parent_obj) {
  PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
  PyUpb_ByNumberMap* map = (void*)PyType_GenericAlloc(s->by_number_map_type, 0);
  map->funcs = funcs;
  map->parent = parent;
  map->parent_obj = parent_obj;
  Py_INCREF(parent_obj);
  return &map->ob_base;
}

static void PyUpb_ByNumberMap_Dealloc(PyObject* _self) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  Py_DECREF(self->parent_obj);
  PyUpb_Dealloc(self);
}

static Py_ssize_t PyUpb_ByNumberMap_Length(PyObject* _self) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  return self->funcs->base.get_elem_count(self->parent);
}

static const void* PyUpb_ByNumberMap_LookupHelper(PyUpb_ByNumberMap* self,
                                                  PyObject* key) {
  long num = PyLong_AsLong(key);
  if (num == -1 && PyErr_Occurred()) {
    PyErr_Clear();
    // Ensure that the key is hashable (this will raise an error if not).
    PyObject_Hash(key);
    return NULL;
  } else {
    return self->funcs->lookup(self->parent, num);
  }
}

static PyObject* PyUpb_ByNumberMap_Subscript(PyObject* _self, PyObject* key) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  const void* elem = PyUpb_ByNumberMap_LookupHelper(self, key);
  if (elem) {
    return self->funcs->base.get_elem_wrapper(elem);
  } else {
    if (!PyErr_Occurred()) {
      PyErr_SetObject(PyExc_KeyError, key);
    }
    return NULL;
  }
}

static int PyUpb_ByNumberMap_AssignSubscript(PyObject* self, PyObject* key,
                                             PyObject* value) {
  PyErr_Format(PyExc_TypeError, PYUPB_MODULE_NAME
               ".ByNumberMap' object does not support item assignment");
  return -1;
}

static PyObject* PyUpb_ByNumberMap_Get(PyObject* _self, PyObject* args) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  PyObject* key;
  PyObject* default_value = Py_None;
  if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
    return NULL;
  }

  const void* elem = PyUpb_ByNumberMap_LookupHelper(self, key);
  if (elem) {
    return self->funcs->base.get_elem_wrapper(elem);
  } else if (PyErr_Occurred()) {
    return NULL;
  } else {
    return PyUpb_NewRef(default_value);
  }
}

static PyObject* PyUpb_ByNumberMap_GetIter(PyObject* _self) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  return PyUpb_ByNumberIterator_New(self->funcs, self->parent,
                                    self->parent_obj);
}

static PyObject* PyUpb_ByNumberMap_Keys(PyObject* _self, PyObject* args) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  int n = self->funcs->base.get_elem_count(self->parent);
  PyObject* ret = PyList_New(n);
  if (!ret) return NULL;
  for (int i = 0; i < n; i++) {
    const void* elem = self->funcs->base.index(self->parent, i);
    PyObject* key = PyLong_FromLong(self->funcs->get_elem_num(elem));
    if (!key) goto error;
    PyList_SetItem(ret, i, key);
  }
  return ret;

error:
  Py_XDECREF(ret);
  return NULL;
}

static PyObject* PyUpb_ByNumberMap_Values(PyObject* _self, PyObject* args) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  int n = self->funcs->base.get_elem_count(self->parent);
  PyObject* ret = PyList_New(n);
  if (!ret) return NULL;
  for (int i = 0; i < n; i++) {
    const void* elem = self->funcs->base.index(self->parent, i);
    PyObject* py_elem = self->funcs->base.get_elem_wrapper(elem);
    if (!py_elem) goto error;
    PyList_SetItem(ret, i, py_elem);
  }
  return ret;

error:
  Py_XDECREF(ret);
  return NULL;
}

static PyObject* PyUpb_ByNumberMap_Items(PyObject* _self, PyObject* args) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  int n = self->funcs->base.get_elem_count(self->parent);
  PyObject* ret = PyList_New(n);
  PyObject* item;
  PyObject* py_elem;
  if (!ret) return NULL;
  for (int i = 0; i < n; i++) {
    const void* elem = self->funcs->base.index(self->parent, i);
    int number = self->funcs->get_elem_num(elem);
    item = PyTuple_New(2);
    py_elem = self->funcs->base.get_elem_wrapper(elem);
    if (!item || !py_elem) goto error;
    PyTuple_SetItem(item, 0, PyLong_FromLong(number));
    PyTuple_SetItem(item, 1, py_elem);
    PyList_SetItem(ret, i, item);
  }
  return ret;

error:
  Py_XDECREF(py_elem);
  Py_XDECREF(item);
  Py_XDECREF(ret);
  return NULL;
}

static int PyUpb_ByNumberMap_Contains(PyObject* _self, PyObject* key) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  const void* elem = PyUpb_ByNumberMap_LookupHelper(self, key);
  if (elem) return 1;
  if (PyErr_Occurred()) return -1;
  return 0;
}

// A mapping container can only be equal to another mapping container, or (for
// backward compatibility) to a dict containing the same items.
// Returns 1 if equal, 0 if unequal, -1 on error.
static int PyUpb_ByNumberMap_IsEqual(PyUpb_ByNumberMap* self, PyObject* other) {
  // Check the identity of C++ pointers.
  if (PyObject_TypeCheck(other, Py_TYPE(self))) {
    PyUpb_ByNumberMap* other_map = (void*)other;
    return self->parent == other_map->parent && self->funcs == other_map->funcs;
  }

  if (!PyDict_Check(other)) return 0;

  PyObject* self_dict = PyDict_New();
  PyDict_Merge(self_dict, (PyObject*)self, 0);
  int eq = PyObject_RichCompareBool(self_dict, other, Py_EQ);
  Py_DECREF(self_dict);
  return eq;
}

static PyObject* PyUpb_ByNumberMap_RichCompare(PyObject* _self, PyObject* other,
                                               int opid) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  if (opid != Py_EQ && opid != Py_NE) {
    Py_RETURN_NOTIMPLEMENTED;
  }
  bool ret = PyUpb_ByNumberMap_IsEqual(self, other);
  if (opid == Py_NE) ret = !ret;
  return PyBool_FromLong(ret);
}

static PyMethodDef PyUpb_ByNumberMap_Methods[] = {
    {"get", (PyCFunction)&PyUpb_ByNumberMap_Get, METH_VARARGS},
    {"keys", PyUpb_ByNumberMap_Keys, METH_NOARGS},
    {"values", PyUpb_ByNumberMap_Values, METH_NOARGS},
    {"items", PyUpb_ByNumberMap_Items, METH_NOARGS},
    {NULL}};

static PyType_Slot PyUpb_ByNumberMap_Slots[] = {
    {Py_mp_ass_subscript, PyUpb_ByNumberMap_AssignSubscript},
    {Py_mp_length, PyUpb_ByNumberMap_Length},
    {Py_mp_subscript, PyUpb_ByNumberMap_Subscript},
    {Py_sq_contains, &PyUpb_ByNumberMap_Contains},
    {Py_tp_dealloc, &PyUpb_ByNumberMap_Dealloc},
    {Py_tp_iter, PyUpb_ByNumberMap_GetIter},
    {Py_tp_methods, &PyUpb_ByNumberMap_Methods},
    {Py_tp_repr, &PyUpb_DescriptorMap_Repr},
    {Py_tp_richcompare, &PyUpb_ByNumberMap_RichCompare},
    {0, NULL},
};

static PyType_Spec PyUpb_ByNumberMap_Spec = {
    PYUPB_MODULE_NAME "._ByNumberMap",  // tp_name
    sizeof(PyUpb_ByNumberMap),          // tp_basicsize
    0,                                  // tp_itemsize
    Py_TPFLAGS_DEFAULT,                 // tp_flags
    PyUpb_ByNumberMap_Slots,
};

// -----------------------------------------------------------------------------
// Top Level
// -----------------------------------------------------------------------------

bool PyUpb_InitDescriptorContainers(PyObject* m) {
  PyUpb_ModuleState* s = PyUpb_ModuleState_GetFromModule(m);

  s->by_name_map_type = PyUpb_AddClass(m, &PyUpb_ByNameMap_Spec);
  s->by_number_map_type = PyUpb_AddClass(m, &PyUpb_ByNumberMap_Spec);
  s->by_name_iterator_type = PyUpb_AddClass(m, &PyUpb_ByNameIterator_Spec);
  s->by_number_iterator_type = PyUpb_AddClass(m, &PyUpb_ByNumberIterator_Spec);
  s->generic_sequence_type = PyUpb_AddClass(m, &PyUpb_GenericSequence_Spec);

  return s->by_name_map_type && s->by_number_map_type &&
         s->by_name_iterator_type && s->by_number_iterator_type &&
         s->generic_sequence_type;
}
