in watchman/python/pywatchman/bser.c [395:504]
static int bser_recursive(bser_t* bser, PyObject* val) {
if (PyBool_Check(val)) {
if (val == Py_True) {
return bser_append(bser, &bser_true, sizeof(bser_true));
}
return bser_append(bser, &bser_false, sizeof(bser_false));
}
if (val == Py_None) {
return bser_append(bser, &bser_null, sizeof(bser_null));
}
// Python 3 has one integer type.
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(val)) {
return bser_long(bser, PyInt_AS_LONG(val));
}
#endif // PY_MAJOR_VERSION < 3
if (PyLong_Check(val)) {
return bser_long(bser, PyLong_AsLongLong(val));
}
if (PyBytes_Check(val) || PyUnicode_Check(val)) {
return bser_bytestring(bser, val);
}
if (PyFloat_Check(val)) {
double dval = PyFloat_AS_DOUBLE(val);
char sz = BSER_REAL;
if (!bser_append(bser, &sz, sizeof(sz))) {
return 0;
}
return bser_append(bser, (char*)&dval, sizeof(dval));
}
if (PyList_Check(val)) {
Py_ssize_t i, len = PyList_GET_SIZE(val);
if (!bser_append(bser, &bser_array_hdr, sizeof(bser_array_hdr))) {
return 0;
}
if (!bser_long(bser, len)) {
return 0;
}
for (i = 0; i < len; i++) {
PyObject* ele = PyList_GET_ITEM(val, i);
if (!bser_recursive(bser, ele)) {
return 0;
}
}
return 1;
}
if (PyTuple_Check(val)) {
Py_ssize_t i, len = PyTuple_GET_SIZE(val);
if (!bser_append(bser, &bser_array_hdr, sizeof(bser_array_hdr))) {
return 0;
}
if (!bser_long(bser, len)) {
return 0;
}
for (i = 0; i < len; i++) {
PyObject* ele = PyTuple_GET_ITEM(val, i);
if (!bser_recursive(bser, ele)) {
return 0;
}
}
return 1;
}
if (PyMapping_Check(val)) {
Py_ssize_t len = PyMapping_Length(val);
Py_ssize_t pos = 0;
PyObject *key, *ele;
if (!bser_append(bser, &bser_object_hdr, sizeof(bser_object_hdr))) {
return 0;
}
if (!bser_long(bser, len)) {
return 0;
}
while (PyDict_Next(val, &pos, &key, &ele)) {
if (!bser_bytestring(bser, key)) {
return 0;
}
if (!bser_recursive(bser, ele)) {
return 0;
}
}
return 1;
}
PyErr_SetString(PyExc_ValueError, "Unsupported value type");
return 0;
}