Skip to content

Commit e464954

Browse files
committed
only abi stable functions
1 parent e2d3bd5 commit e464954

File tree

1 file changed

+37
-18
lines changed

1 file changed

+37
-18
lines changed

source/cbor.c

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -183,30 +183,49 @@ static PyObject *s_cbor_encoder_write_pyobject(struct aws_cbor_encoder *encoder,
183183
/**
184184
* TODO: timestamp <-> datetime?? Decimal fraction <-> decimal??
185185
*/
186-
if (PyLong_CheckExact(py_object)) {
187-
return s_cbor_encoder_write_pylong(encoder, py_object);
188-
} else if (PyFloat_CheckExact(py_object)) {
189-
return s_cbor_encoder_write_pyobject_as_float(encoder, py_object);
190-
} else if (PyBool_Check(py_object)) {
191-
return s_cbor_encoder_write_pyobject_as_bool(encoder, py_object);
192-
} else if (PyBytes_CheckExact(py_object)) {
193-
return s_cbor_encoder_write_pyobject_as_bytes(encoder, py_object);
194-
} else if (PyUnicode_Check(py_object)) {
186+
187+
/* Handle None first as it's a singleton, not a type */
188+
if (py_object == Py_None) {
189+
aws_cbor_encoder_write_null(encoder);
190+
Py_RETURN_NONE;
191+
}
192+
193+
/* Get type once for efficiency - PyObject_Type returns a new reference */
194+
/* https://docs.python.org/3/c-api/structures.html#c.Py_TYPE is not a stable API until 3.14, so that we cannot use
195+
* it. */
196+
PyObject *type = PyObject_Type(py_object);
197+
if (!type) {
198+
return NULL;
199+
}
200+
201+
PyObject *result = NULL;
202+
203+
/* Exact type matches first (no subclasses) */
204+
if (type == (PyObject *)&PyLong_Type) {
205+
result = s_cbor_encoder_write_pylong(encoder, py_object);
206+
} else if (type == (PyObject *)&PyFloat_Type) {
207+
result = s_cbor_encoder_write_pyobject_as_float(encoder, py_object);
208+
} else if (type == (PyObject *)&PyBool_Type) {
209+
result = s_cbor_encoder_write_pyobject_as_bool(encoder, py_object);
210+
} else if (type == (PyObject *)&PyBytes_Type) {
211+
result = s_cbor_encoder_write_pyobject_as_bytes(encoder, py_object);
212+
} else if (PyType_IsSubtype((PyTypeObject *)type, &PyUnicode_Type)) {
195213
/* Allow subclasses of `str` */
196-
return s_cbor_encoder_write_pyobject_as_text(encoder, py_object);
197-
} else if (PyList_Check(py_object)) {
214+
result = s_cbor_encoder_write_pyobject_as_text(encoder, py_object);
215+
} else if (PyType_IsSubtype((PyTypeObject *)type, &PyList_Type)) {
198216
/* Write py_list, allow subclasses of `list` */
199-
return s_cbor_encoder_write_pylist(encoder, py_object);
200-
} else if (PyDict_Check(py_object)) {
217+
result = s_cbor_encoder_write_pylist(encoder, py_object);
218+
} else if (PyType_IsSubtype((PyTypeObject *)type, &PyDict_Type)) {
201219
/* Write py_dict, allow subclasses of `dict` */
202-
return s_cbor_encoder_write_pydict(encoder, py_object);
203-
} else if (py_object == Py_None) {
204-
aws_cbor_encoder_write_null(encoder);
220+
result = s_cbor_encoder_write_pydict(encoder, py_object);
205221
} else {
206-
PyErr_Format(PyExc_ValueError, "Not supported type %R", (PyObject *)Py_TYPE(py_object));
222+
/* Unsupported type */
223+
PyErr_Format(PyExc_ValueError, "Not supported type %R", type);
207224
}
208225

209-
Py_RETURN_NONE;
226+
/* Release the type reference */
227+
Py_DECREF(type);
228+
return result;
210229
}
211230

212231
/*********************************** BINDINGS ***********************************************/

0 commit comments

Comments
 (0)