// 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 "google/protobuf/breaking_changes.h"
#include "python/descriptor.h"
#include "python/protobuf.h"
#include "upb/reflection/def.h"

// Must be last.
#include "upb/port/def.inc"

// 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)

typedef enum {
  kPyUpb_CompareEqual,
  kPyUpb_CompareNotEqual,
  kPyUpb_CompareError,
  kPyUpb_CompareNotImplemented,
} PyUpb_CompareResult;

static PyUpb_CompareResult PyUpb_CompareUnrecognized(void) {
#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED
  return kPyUpb_CompareNotImplemented;
#else
  if (PyErr_WarnEx(
          PyExc_FutureWarning,
          "Comparing descriptor containers with unrecognized types will return "
          "NotImplemented in 2027.",
          3) < 0) {
    return kPyUpb_CompareError;
  }
  return kPyUpb_CompareNotEqual;
#endif
}

// -----------------------------------------------------------------------------
// 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* pool;      // DescriptorPool instance, 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->pool);
  PyUpb_Dealloc(self);
}

static PyObject* PyUpb_ByNameIterator_New(const PyUpb_ByNameMap_Funcs* funcs,
                                          const void* parent, PyObject* pool) {
  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->pool = pool;
  iter->index = 0;
  Py_INCREF(iter->pool);
  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* pool;      // DescriptorPool instance, 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->pool);
  PyUpb_Dealloc(self);
}

static PyObject* PyUpb_ByNumberIterator_New(
    const PyUpb_ByNumberMap_Funcs* funcs, const void* parent, PyObject* pool) {
  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->pool = pool;
  iter->index = 0;
  Py_INCREF(iter->pool);
  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* pool;      // DescriptorPool instance, 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->pool);
  PyUpb_Dealloc(self);
}

PyObject* PyUpb_GenericSequence_New(const PyUpb_GenericSequence_Funcs* funcs,
                                    const void* parent, PyObject* pool) {
  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->pool = pool;
  Py_XINCREF(pool);
  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(self->pool, elem);
}

// A sequence container can only be equal to another sequence container, or (for
// backward compatibility) to a list containing the same items.
static PyUpb_CompareResult 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;
    if (self->parent == other_seq->parent && self->funcs == other_seq->funcs) {
      return kPyUpb_CompareEqual;
    } else {
      return kPyUpb_CompareNotEqual;
    }
  }

  if (!PyList_Check(other)) {
    return PyUpb_CompareUnrecognized();
  }

  // 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 kPyUpb_CompareNotEqual;
  }

  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 < 0) return kPyUpb_CompareError;
    if (cmp == 0) return kPyUpb_CompareNotEqual;
  }
  // All items were found and equal
  return kPyUpb_CompareEqual;

error:
  Py_XDECREF(item1);
  return kPyUpb_CompareError;
}

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;
  }
  PyUpb_CompareResult eq = PyUpb_GenericSequence_IsEqual(self, other);
  switch (eq) {
    case kPyUpb_CompareNotImplemented:
#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED
      Py_RETURN_NOTIMPLEMENTED;
#else
      UPB_UNREACHABLE();  // Unreachable when this breaking change is disabled.
#endif
    case kPyUpb_CompareError:
      return NULL;
    case kPyUpb_CompareEqual:
      return PyBool_FromLong(opid == Py_EQ);
    case kPyUpb_CompareNotEqual:
      return PyBool_FromLong(opid == Py_NE);
  }
  return NULL;
}

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(self->pool, 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* pool;      // DescriptorPool instance, 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_CLEAR(self->pool);
  PyUpb_Dealloc(self);
}

PyObject* PyUpb_ByNameMap_New(const PyUpb_ByNameMap_Funcs* funcs,
                              const void* parent, PyObject* pool) {
  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->pool = pool;
  Py_XINCREF(pool);
  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(self->pool, 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) {
    PyObject* pool = self->pool;
    return self->funcs->base.get_elem_wrapper(pool, 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->pool);
}

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;
  PyObject* pool = self->pool;
  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(pool, 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;
  PyObject* pool = self->pool;
  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(pool, 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.
static PyUpb_CompareResult 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;
    if (self->parent == other_map->parent && self->funcs == other_map->funcs) {
      return kPyUpb_CompareEqual;
    } else {
      return kPyUpb_CompareNotEqual;
    }
  }

  if (!PyDict_Check(other)) {
    return PyUpb_CompareUnrecognized();
  }

  PyObject* self_dict = PyDict_New();
  if (PyDict_Merge(self_dict, (PyObject*)self, 0) < 0) {
    Py_DECREF(self_dict);
    return kPyUpb_CompareError;
  }
  int eq = PyObject_RichCompareBool(self_dict, other, Py_EQ);
  Py_DECREF(self_dict);
  if (eq < 0) return kPyUpb_CompareError;
  if (eq == 0) return kPyUpb_CompareNotEqual;
  return kPyUpb_CompareEqual;
}

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;
  }
  PyUpb_CompareResult eq = PyUpb_ByNameMap_IsEqual(self, other);
  switch (eq) {
    case kPyUpb_CompareNotImplemented:
#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED
      Py_RETURN_NOTIMPLEMENTED;
#else
      UPB_UNREACHABLE();  // Unreachable when this breaking change is disabled.
#endif
    case kPyUpb_CompareError:
      return NULL;
    case kPyUpb_CompareEqual:
      return PyBool_FromLong(opid == Py_EQ);
    case kPyUpb_CompareNotEqual:
      return PyBool_FromLong(opid == Py_NE);
  }
  return NULL;
}

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* pool;      // DescriptorPool instance, 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* pool) {
  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->pool = pool;
  Py_INCREF(pool);
  return &map->ob_base;
}

static void PyUpb_ByNumberMap_Dealloc(PyObject* _self) {
  PyUpb_ByNumberMap* self = PyUpb_ByNumberMap_Self(_self);
  Py_DECREF(self->pool);
  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(self->pool, 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(self->pool, 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->pool);
}

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(self->pool, 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(self->pool, 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.
static PyUpb_CompareResult 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;
    if (self->parent == other_map->parent && self->funcs == other_map->funcs) {
      return kPyUpb_CompareEqual;
    } else {
      return kPyUpb_CompareNotEqual;
    }
  }

  if (!PyDict_Check(other)) {
    return PyUpb_CompareUnrecognized();
  }

  PyObject* self_dict = PyDict_New();
  if (PyDict_Merge(self_dict, (PyObject*)self, 0) < 0) {
    Py_DECREF(self_dict);
    return kPyUpb_CompareError;
  }
  int eq = PyObject_RichCompareBool(self_dict, other, Py_EQ);
  Py_DECREF(self_dict);
  if (eq < 0) return kPyUpb_CompareError;
  if (eq == 0) return kPyUpb_CompareNotEqual;
  return kPyUpb_CompareEqual;
}

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;
  }
  PyUpb_CompareResult eq = PyUpb_ByNumberMap_IsEqual(self, other);
  switch (eq) {
    case kPyUpb_CompareNotImplemented:
#if PROTOBUF_PY_FUTURE_CONTAINER_EQ_RETURNS_NOTIMPLEMENTED
      Py_RETURN_NOTIMPLEMENTED;
#else
      UPB_UNREACHABLE();  // Unreachable when this breaking change is disabled.
#endif
    case kPyUpb_CompareError:
      return NULL;
    case kPyUpb_CompareEqual:
      return PyBool_FromLong(opid == Py_EQ);
    case kPyUpb_CompareNotEqual:
      return PyBool_FromLong(opid == Py_NE);
  }
  return NULL;
}

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;
}

#include "upb/port/undef.inc"
