Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 79 additions & 61 deletions msgspec/_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -10441,6 +10441,7 @@ PyDoc_STRVAR(JSONEncoder__doc__,
" The size of the internal static write buffer."
);

static int json_encode_inline(EncoderState*, PyObject*);
static int json_encode(EncoderState*, PyObject*);

static MS_INLINE int
Expand All @@ -10464,7 +10465,7 @@ json_encode_false(EncoderState *self)
return ms_write(self, buf, 5);
}

static int
static MS_NOINLINE int
json_encode_long(EncoderState *self, PyObject *obj) {
char buf[20];
char *p = &buf[20];
Expand Down Expand Up @@ -10504,7 +10505,7 @@ json_encode_long_as_str(EncoderState *self, PyObject *obj) {
return ms_write(self, "\"", 1);
}

static int
static MS_NOINLINE int
json_encode_float(EncoderState *self, PyObject *obj) {
char buf[24];
double x = PyFloat_AS_DOUBLE(obj);
Expand Down Expand Up @@ -10588,7 +10589,7 @@ json_write_str_fragment(
return i + 1;
}

static int
static MS_NOINLINE int
json_encode_str(EncoderState *self, PyObject *obj) {
Py_ssize_t i, len, start = 0;
const char* buf = unicode_str_and_size(obj, &len);
Expand Down Expand Up @@ -10759,19 +10760,17 @@ json_encode_datetime(EncoderState *self, PyObject *obj)
return ms_write(self, buf, size + 2);
}

static int
json_encode_list(EncoderState *self, PyObject *obj)
static MS_INLINE int
json_encode_sequence(EncoderState *self, Py_ssize_t size, PyObject **arr)
{
Py_ssize_t i, len;
int status = -1;

len = PyList_GET_SIZE(obj);
if (len == 0) return ms_write(self, "[]", 2);
if (size == 0) return ms_write(self, "[]", 2);

if (ms_write(self, "[", 1) < 0) return -1;
if (Py_EnterRecursiveCall(" while serializing an object")) return -1;
for (i = 0; i < len; i++) {
if (json_encode(self, PyList_GET_ITEM(obj, i)) < 0) goto cleanup;
for (Py_ssize_t i = 0; i < size; i++) {
if (json_encode_inline(self, *(arr + i)) < 0) goto cleanup;
if (ms_write(self, ",", 1) < 0) goto cleanup;
}
/* Overwrite trailing comma with ] */
Expand All @@ -10782,6 +10781,22 @@ json_encode_list(EncoderState *self, PyObject *obj)
return status;
}

static MS_NOINLINE int
json_encode_list(EncoderState *self, PyObject *obj)
{
return json_encode_sequence(
self, PyList_GET_SIZE(obj), ((PyListObject *)obj)->ob_item
);
}

static MS_NOINLINE int
json_encode_tuple(EncoderState *self, PyObject *obj)
{
return json_encode_sequence(
self, PyTuple_GET_SIZE(obj), ((PyTupleObject *)obj)->ob_item
);
}

static int
json_encode_set(EncoderState *self, PyObject *obj)
{
Expand All @@ -10796,30 +10811,7 @@ json_encode_set(EncoderState *self, PyObject *obj)
if (ms_write(self, "[", 1) < 0) return -1;
if (Py_EnterRecursiveCall(" while serializing an object")) return -1;
while (_PySet_NextEntry(obj, &ppos, &item, &hash)) {
if (json_encode(self, item) < 0) goto cleanup;
if (ms_write(self, ",", 1) < 0) goto cleanup;
}
/* Overwrite trailing comma with ] */
*(self->output_buffer_raw + self->output_len - 1) = ']';
status = 0;
cleanup:
Py_LeaveRecursiveCall();
return status;
}

static int
json_encode_tuple(EncoderState *self, PyObject *obj)
{
Py_ssize_t i, len;
int status = -1;

len = PyTuple_GET_SIZE(obj);
if (len == 0) return ms_write(self, "[]", 2);

if (ms_write(self, "[", 1) < 0) return -1;
if (Py_EnterRecursiveCall(" while serializing an object")) return -1;
for (i = 0; i < len; i++) {
if (json_encode(self, PyTuple_GET_ITEM(obj, i)) < 0) goto cleanup;
if (json_encode_inline(self, item) < 0) goto cleanup;
if (ms_write(self, ",", 1) < 0) goto cleanup;
}
/* Overwrite trailing comma with ] */
Expand Down Expand Up @@ -10868,7 +10860,7 @@ json_encode_dict_key(EncoderState *self, PyObject *obj) {
}
}

static int
static MS_NOINLINE int
json_encode_dict(EncoderState *self, PyObject *obj)
{
PyObject *key, *val;
Expand All @@ -10887,7 +10879,7 @@ json_encode_dict(EncoderState *self, PyObject *obj)
if (json_encode_dict_key(self, key) < 0) goto cleanup;
}
if (ms_write(self, ":", 1) < 0) goto cleanup;
if (json_encode(self, val) < 0) goto cleanup;
if (json_encode_inline(self, val) < 0) goto cleanup;
if (ms_write(self, ",", 1) < 0) goto cleanup;
}
/* Overwrite trailing comma with } */
Expand Down Expand Up @@ -10966,6 +10958,19 @@ json_encode_object(EncoderState *self, PyObject *obj)
return status;
}

static int
json_encode_struct_tag(EncoderState *self, PyObject *obj)
{
PyTypeObject *type = Py_TYPE(obj);

if (type == &PyUnicode_Type) {
return json_encode_str(self, obj);
}
else {
return json_encode_long(self, obj);
}
}

static int
json_encode_struct_default(
EncoderState *self, StructMetaObject *struct_type, PyObject *obj
Expand All @@ -10984,7 +10989,7 @@ json_encode_struct_default(
if (tag_value != NULL) {
if (json_encode_str(self, tag_field) < 0) goto cleanup;
if (ms_write(self, ":", 1) < 0) goto cleanup;
if (json_encode(self, tag_value) < 0) goto cleanup;
if (json_encode_struct_tag(self, tag_value) < 0) goto cleanup;
if (ms_write(self, ",", 1) < 0) goto cleanup;
}
for (i = 0; i < nfields; i++) {
Expand Down Expand Up @@ -11024,7 +11029,7 @@ json_encode_struct_omit_defaults(
if (tag_value != NULL) {
if (json_encode_str(self, tag_field) < 0) goto cleanup;
if (ms_write(self, ":", 1) < 0) goto cleanup;
if (json_encode(self, tag_value) < 0) goto cleanup;
if (json_encode_struct_tag(self, tag_value) < 0) goto cleanup;
if (ms_write(self, ",", 1) < 0) goto cleanup;
}

Expand Down Expand Up @@ -11076,7 +11081,7 @@ json_encode_struct_array_like(
if (ms_write(self, "[", 1) < 0) return -1;
if (Py_EnterRecursiveCall(" while serializing an object")) return -1;
if (tag_value != NULL) {
if (json_encode(self, tag_value) < 0) goto cleanup;
if (json_encode_struct_tag(self, tag_value) < 0) goto cleanup;
if (ms_write(self, ",", 1) < 0) goto cleanup;
}
for (Py_ssize_t i = 0; i < nfields; i++) {
Expand Down Expand Up @@ -11109,11 +11114,8 @@ json_encode_struct(EncoderState *self, PyObject *obj)
}
}

static int
json_encode(EncoderState *self, PyObject *obj)
{
PyTypeObject *type = Py_TYPE(obj);

static MS_NOINLINE int
json_encode_uncommon(EncoderState *self, PyTypeObject *type, PyObject *obj) {
if (obj == Py_None) {
return json_encode_none(self);
}
Expand All @@ -11123,27 +11125,12 @@ json_encode(EncoderState *self, PyObject *obj)
else if (obj == Py_False) {
return json_encode_false(self);
}
else if (type == &PyLong_Type) {
return json_encode_long(self, obj);
}
else if (type == &PyFloat_Type) {
return json_encode_float(self, obj);
}
else if (type == &PyUnicode_Type) {
return json_encode_str(self, obj);
}
else if (PyList_Check(obj)) {
return json_encode_list(self, obj);
else if (Py_TYPE(type) == &StructMetaType) {
return json_encode_struct(self, obj);
}
else if (PyTuple_Check(obj)) {
return json_encode_tuple(self, obj);
}
else if (PyDict_Check(obj)) {
return json_encode_dict(self, obj);
}
else if (Py_TYPE(type) == &StructMetaType) {
return json_encode_struct(self, obj);
}
else if (type == PyDateTimeAPI->DateTimeType) {
return json_encode_datetime(self, obj);
}
Expand Down Expand Up @@ -11196,6 +11183,37 @@ json_encode(EncoderState *self, PyObject *obj)
return ms_encode_err_type_unsupported(type);
}

static MS_INLINE int
json_encode_inline(EncoderState *self, PyObject *obj)
{
PyTypeObject *type = Py_TYPE(obj);

if (type == &PyUnicode_Type) {
return json_encode_str(self, obj);
}
else if (type == &PyLong_Type) {
return json_encode_long(self, obj);
}
else if (type == &PyFloat_Type) {
return json_encode_float(self, obj);
}
else if (PyList_Check(obj)) {
return json_encode_list(self, obj);
}
else if (PyDict_Check(obj)) {
return json_encode_dict(self, obj);
}
else {
return json_encode_uncommon(self, type, obj);
}
}

static int
json_encode(EncoderState *self, PyObject *obj)
{
return json_encode_inline(self, obj);
}

static PyObject*
JSONEncoder_encode_into(Encoder *self, PyObject *const *args, Py_ssize_t nargs)
{
Expand Down