From: Stuart Prescott <stuart@debian.org>
Date: Mon, 8 Dec 2025 17:19:03 +1100
Subject: Use packaged ujson

---
 srsly/_json_api.py                    |    2 +-
 srsly/tests/ujson/334-reproducer.json |  857 --------------------------
 srsly/tests/ujson/__init__.py         |    0
 srsly/tests/ujson/test_ujson.py       |  991 ------------------------------
 srsly/ujson/JSONtoObj.c               |  261 --------
 srsly/ujson/__init__.py               |    1 -
 srsly/ujson/lib/dconv_wrapper.cc      |   58 --
 srsly/ujson/lib/ultrajson.h           |  324 ----------
 srsly/ujson/lib/ultrajsondec.c        |  891 ---------------------------
 srsly/ujson/lib/ultrajsonenc.c        | 1067 ---------------------------------
 srsly/ujson/objToJSON.c               |  984 ------------------------------
 srsly/ujson/py_defines.h              |   53 --
 srsly/ujson/ujson.c                   |  113 ----
 srsly/ujson/version.h                 |   39 --
 14 files changed, 1 insertion(+), 5640 deletions(-)
 delete mode 100644 srsly/tests/ujson/334-reproducer.json
 delete mode 100644 srsly/tests/ujson/__init__.py
 delete mode 100644 srsly/tests/ujson/test_ujson.py
 delete mode 100644 srsly/ujson/JSONtoObj.c
 delete mode 100644 srsly/ujson/__init__.py
 delete mode 100644 srsly/ujson/lib/dconv_wrapper.cc
 delete mode 100644 srsly/ujson/lib/ultrajson.h
 delete mode 100644 srsly/ujson/lib/ultrajsondec.c
 delete mode 100644 srsly/ujson/lib/ultrajsonenc.c
 delete mode 100644 srsly/ujson/objToJSON.c
 delete mode 100644 srsly/ujson/py_defines.h
 delete mode 100644 srsly/ujson/ujson.c
 delete mode 100644 srsly/ujson/version.h

diff --git a/srsly/_json_api.py b/srsly/_json_api.py
index 24d25fd..6c48c1b 100644
--- a/srsly/_json_api.py
+++ b/srsly/_json_api.py
@@ -3,7 +3,7 @@ import sys
 import json as _builtin_json
 import gzip
 
-from . import ujson
+import ujson
 from .util import force_path, force_string, FilePath, JSONInput, JSONOutput
 
 
diff --git a/srsly/tests/ujson/334-reproducer.json b/srsly/tests/ujson/334-reproducer.json
deleted file mode 100644
index b53fcd5..0000000
--- a/srsly/tests/ujson/334-reproducer.json
+++ /dev/null
@@ -1,857 +0,0 @@
-{
-	"ak.somestring.internal.Shadow": {
-		"id": 33300002,
-		"init_state": "(bk.action.array.Make, (bk.action.i32.Const, 0))",
-		"child": {
-			"ak.somestring.Flexbox": {
-				"flex_direction": "column",
-				"align_items": "stretch",
-				"children": [
-					{
-						"ak.somestring.Collection": {
-							"id": 33300001,
-							"snap": "center",
-							"direction": "row",
-							"children": [
-								{
-									"ak.somestring.Flexbox": {
-										"decoration": {
-											"ak.somestring.BoxDecoration": {
-												"background": {
-													"ak.somestring.ColorDrawable": {
-														"color": "#2c8932"
-													}
-												}
-											}
-										},
-										"children": [
-											{
-												"ak.somestring.Flexbox": {
-													"flex_direction": "column",
-													"align_items": "stretch",
-													"children": [
-														{
-															"ak.somestring.Flexbox": {
-																"flex_direction": "column",
-																"align_items": "stretch",
-																"children": [
-																	{
-																		"ak.somestring.Flexbox": {
-																			"children": [
-																				{
-																					"ls.components.Image": {
-																						"media_id": "10156403921218138",
-																						"preview_url": "https://scontent.xx.whoaa.net/v/t1.0-9/51099660_10156403921233138_3677795704043995136_n.jpg?_nc_cat=102&_nc_log=1&_nc_oc=AQk3Td-w9KpopLL2N1jgZ4WDMuxUyuGY3ZvY4mDSCk8W9-GjsFPi2S4gVQk0Y3A5ZaaQf7ASvQ2s_eR85kTmFvr0&_nc_ad=z-m&_nc_cid=0&_nc_zor=9&_nc_ht=scontent.xx&oh=fb16b0d60b13817a505f583cc9dad1eb&oe=5CBCDB46",
-																						"height": 278,
-																						"width": 156
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"grow": 1
-																				}
-																			}
-																		}
-																	},
-																	{
-																		"ak.somestring.Flexbox": {
-																			"flex_direction": "column",
-																			"align_items": "stretch",
-																			"children": [
-																				{
-																					"ak.somestring.Flexbox": {
-																						"flex_direction": "row",
-																						"align_items": "stretch",
-																						"children": [
-																							{
-																								"ak.somestring.Flexbox": {
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#ffffff"
-																												}
-																											}
-																										}
-																									},
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							},
-																							{
-																								"ak.somestring.Flexbox": {
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#ffffff"
-																												}
-																											}
-																										}
-																									},
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							},
-																							{
-																								"ak.somestring.Flexbox": {
-																									"flex_direction": "row",
-																									"align_items": "stretch",
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#ffffff"
-																												}
-																											}
-																										}
-																									},
-																									"children": [
-																										{
-																											"ak.somestring.Flexbox": {
-																												"id": 33300004,
-																												"_style": {
-																													"flex": {
-																														"grow": 1
-																													}
-																												}
-																											}
-																										}
-																									],
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"height": "2dp",
-																								"margin_left": "4dp"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"position_type": "absolute",
-																					"left": "0dp",
-																					"top": "10dp",
-																					"margin_top": "10dp",
-																					"right": "0dp",
-																					"height": "2dp",
-																					"width": "100%"
-																				}
-																			}
-																		}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"grow": 1
-																	}
-																}
-															}
-														},
-														{
-															"ak.somestring.Flexbox": {
-																"align_items": "flex_start",
-																"children": [
-																	{
-																		"ak.somestring.Flexbox": {
-																			"decoration": {
-																				"ak.somestring.BoxDecoration": {
-																					"corner_radius": "17dp"
-																				}
-																			},
-																			"children": [
-																				{
-																					"ls.components.Image": {
-																						"media_id": "10156403921218138",
-																						"preview_url": "https://scontent.xx.whoaa.net/v/t1.0-9/51099660_10156403921233138_3677795704043995136_n.jpg?_nc_cat=102&_nc_log=1&_nc_oc=AQk3Td-w9KpopLL2N1jgZ4WDMuxUyuGY3ZvY4mDSCk8W9-GjsFPi2S4gVQk0Y3A5ZaaQf7ASvQ2s_eR85kTmFvr0&_nc_ad=z-m&_nc_cid=0&_nc_zor=9&_nc_ht=scontent.xx&oh=fb16b0d60b13817a505f583cc9dad1eb&oe=5CBCDB46",
-																						"height": 34,
-																						"width": 34,
-																						"_style": {
-																							"flex": {
-																								"width": "34dp",
-																								"height": "34dp"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"margin_right": "12dp",
-																					"width": "34dp",
-																					"height": "34dp"
-																				}
-																			}
-																		}
-																	},
-																	{
-																		"ak.somestring.Flexbox": {
-																			"flex_direction": "column",
-																			"align_items": "flex_start",
-																			"children": [
-																				{
-																					"ak.somestring.RichText": {
-																						"children": [
-																							{
-																								"ak.somestring.TextSpan": {
-																									"text": "eric",
-																									"text_size": "15sp",
-																									"text_style": "bold",
-																									"text_color": "#ffffff"
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"margin_bottom": "2dp",
-																								"width": "100%"
-																							}
-																						}
-																					}
-																				},
-																				{
-																					"ak.somestring.RichText": {
-																						"children": [
-																							{
-																								"ak.somestring.TextSpan": {
-																									"text": "8h",
-																									"text_size": "13sp",
-																									"text_style": "normal",
-																									"text_color": "#ffffff"
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"width": "100%"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"width": "100%",
-																					"height": "100%"
-																				}
-																			}
-																		}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"position_type": "absolute",
-																		"top": "30dp",
-																		"left": "10dp",
-																		"height": "48dp"
-																	}
-																}
-															}
-														},
-														{
-															"ak.somestring.Flexbox": {
-																"children": [
-																	{
-																		"ls.components.StoriesReplyBar": {}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"width": "100%",
-																		"height": "45dp",
-																		"margin_top": "auto",
-																		"margin_bottom": "auto"
-																	}
-																}
-															}
-														}
-													],
-													"_style": {
-														"flex": {
-															"position_type": "absolute",
-															"width": "100%",
-															"height": "100%",
-															"grow": 1
-														}
-													}
-												}
-											},
-											{
-												"ak.somestring.Flexbox": {
-													"flex_direction": "column",
-													"align_items": "stretch",
-													"children": [
-														{
-															"ak.somestring.Flexbox": {
-																"flex_direction": "column",
-																"align_items": "stretch",
-																"children": [
-																	{
-																		"ak.somestring.Flexbox": {
-																			"children": [
-																				{
-																					"ls.components.Image": {
-																						"media_id": "10101230968216658",
-																						"preview_url": "https://scontent.xx.whoaa.net/v/t1.0-9/50800535_10101230968226638_6755212111762161664_n.jpg?_nc_cat=101&_nc_log=1&_nc_oc=AQmKcqYvt6DI7aeGk3k_oF6RHSVZkUg7f9hnBCWilyaOGdCWO0-u9_zssC5qGvca6wqsrz3AP0y1RPLPiZj8ycCv&_nc_ad=z-m&_nc_cid=0&_nc_zor=9&_nc_ht=scontent.xx&oh=2fffbab8f0a102d196454ee0138c1850&oe=5CC15206",
-																						"height": 278,
-																						"width": 156
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"grow": 1
-																				}
-																			}
-																		}
-																	},
-																	{
-																		"ak.somestring.Flexbox": {
-																			"flex_direction": "column",
-																			"align_items": "stretch",
-																			"children": [
-																				{
-																					"ak.somestring.Flexbox": {
-																						"flex_direction": "row",
-																						"align_items": "stretch",
-																						"children": [
-																							{
-																								"ak.somestring.Flexbox": {
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#ffffff"
-																												}
-																											}
-																										}
-																									},
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							},
-																							{
-																								"ak.somestring.Flexbox": {
-																									"flex_direction": "row",
-																									"align_items": "stretch",
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#ffffff"
-																												}
-																											}
-																										}
-																									},
-																									"children": [
-																										{
-																											"ak.somestring.Flexbox": {
-																												"id": 33300005,
-																												"_style": {
-																													"flex": {
-																														"grow": 1
-																													}
-																												}
-																											}
-																										}
-																									],
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							},
-																							{
-																								"ak.somestring.Flexbox": {
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#cccccc"
-																												}
-																											}
-																										}
-																									},
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"height": "2dp",
-																								"margin_left": "4dp"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"position_type": "absolute",
-																					"left": "0dp",
-																					"top": "10dp",
-																					"margin_top": "10dp",
-																					"right": "0dp",
-																					"height": "2dp",
-																					"width": "100%"
-																				}
-																			}
-																		}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"grow": 1
-																	}
-																}
-															}
-														},
-														{
-															"ak.somestring.Flexbox": {
-																"align_items": "flex_start",
-																"children": [
-																	{
-																		"ak.somestring.Flexbox": {
-																			"decoration": {
-																				"ak.somestring.BoxDecoration": {
-																					"corner_radius": "17dp"
-																				}
-																			},
-																			"children": [
-																				{
-																					"ls.components.Image": {
-																						"media_id": "10101230968216658",
-																						"preview_url": "https://scontent.xx.whoaa.net/v/t1.0-9/50800535_10101230968226638_6755212111762161664_n.jpg?_nc_cat=101&_nc_log=1&_nc_oc=AQmKcqYvt6DI7aeGk3k_oF6RHSVZkUg7f9hnBCWilyaOGdCWO0-u9_zssC5qGvca6wqsrz3AP0y1RPLPiZj8ycCv&_nc_ad=z-m&_nc_cid=0&_nc_zor=9&_nc_ht=scontent.xx&oh=2fffbab8f0a102d196454ee0138c1850&oe=5CC15206",
-																						"height": 34,
-																						"width": 34,
-																						"_style": {
-																							"flex": {
-																								"width": "34dp",
-																								"height": "34dp"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"margin_right": "12dp",
-																					"width": "34dp",
-																					"height": "34dp"
-																				}
-																			}
-																		}
-																	},
-																	{
-																		"ak.somestring.Flexbox": {
-																			"flex_direction": "column",
-																			"align_items": "flex_start",
-																			"children": [
-																				{
-																					"ak.somestring.RichText": {
-																						"children": [
-																							{
-																								"ak.somestring.TextSpan": {
-																									"text": "eric",
-																									"text_size": "15sp",
-																									"text_style": "bold",
-																									"text_color": "#ffffff"
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"margin_bottom": "2dp",
-																								"width": "100%"
-																							}
-																						}
-																					}
-																				},
-																				{
-																					"ak.somestring.RichText": {
-																						"children": [
-																							{
-																								"ak.somestring.TextSpan": {
-																									"text": "2h",
-																									"text_size": "13sp",
-																									"text_style": "normal",
-																									"text_color": "#ffffff"
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"width": "100%"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"width": "100%",
-																					"height": "100%"
-																				}
-																			}
-																		}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"position_type": "absolute",
-																		"top": "30dp",
-																		"left": "10dp",
-																		"height": "48dp"
-																	}
-																}
-															}
-														},
-														{
-															"ak.somestring.Flexbox": {
-																"children": [
-																	{
-																		"ls.components.StoriesReplyBar": {}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"width": "100%",
-																		"height": "45dp",
-																		"margin_top": "auto",
-																		"margin_bottom": "auto"
-																	}
-																}
-															}
-														}
-													],
-													"_style": {
-														"flex": {
-															"position_type": "absolute",
-															"width": "100%",
-															"height": "100%",
-															"grow": 1
-														}
-													}
-												}
-											},
-											{
-												"ak.somestring.Flexbox": {
-													"flex_direction": "column",
-													"align_items": "stretch",
-													"children": [
-														{
-															"ak.somestring.Flexbox": {
-																"flex_direction": "column",
-																"align_items": "stretch",
-																"children": [
-																	{
-																		"ak.somestring.Flexbox": {
-																			"children": [
-																				{
-																					"ls.components.Video": {
-																						"media_id": "10156395664922983",
-																						"video_url": "https://video.xx.whoaa.net/v/t42.9040-2/51636103_316525608877874_407931582842667008_n.mp4?_nc_cat=109&efg=eyJ2ZW5jb2RlX3RhZyI6InN2ZV9oZCJ9&_nc_log=1&_nc_oc=AQm6aMctRAFdMe3C66upF2JulQP4mV3Hd4THkueZex952PR389F6Ay9XHm1S40dV1x7M1I-fAW5y3iH7JlQ3MgDM&_nc_ht=video.xx&oh=e17b1f7ec67619d57a5b1cda5e076fef&oe=5C587F7D",
-																						"preview_url": "https://scontent.xx.whoaa.net/v/t15.5256-10/s960x960/51767715_10156395667952983_4168426706077483008_n.jpg?_nc_cat=104&_nc_log=1&_nc_oc=AQnVwEZk2vG8Q3TcoR0SxdXSi8rL_GaST2aH3i9auDcDnJNTRKvuYEFfd_qKGBhmD4-bo-f8BY5j9jHyit765O7P&_nc_ad=z-m&_nc_cid=0&_nc_zor=9&_nc_ht=scontent.xx&oh=9a17e4bcf8a2a9aabc21d2ecf9f8611b&oe=5CB3D14B",
-																						"show_media_play_button": false,
-																						"media_height": 960,
-																						"media_width": 540
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"grow": 1
-																				}
-																			}
-																		}
-																	},
-																	{
-																		"ak.somestring.Flexbox": {
-																			"flex_direction": "column",
-																			"align_items": "stretch",
-																			"children": [
-																				{
-																					"ak.somestring.Flexbox": {
-																						"flex_direction": "row",
-																						"align_items": "stretch",
-																						"children": [
-																							{
-																								"ak.somestring.Flexbox": {
-																									"flex_direction": "row",
-																									"align_items": "stretch",
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#ffffff"
-																												}
-																											}
-																										}
-																									},
-																									"children": [
-																										{
-																											"ak.somestring.Flexbox": {
-																												"id": 33300006,
-																												"_style": {
-																													"flex": {
-																														"grow": 1
-																													}
-																												}
-																											}
-																										}
-																									],
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							},
-																							{
-																								"ak.somestring.Flexbox": {
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#cccccc"
-																												}
-																											}
-																										}
-																									},
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							},
-																							{
-																								"ak.somestring.Flexbox": {
-																									"decoration": {
-																										"ak.somestring.BoxDecoration": {
-																											"background": {
-																												"ak.somestring.ColorDrawable": {
-																													"color": "#cccccc"
-																												}
-																											}
-																										}
-																									},
-																									"_style": {
-																										"flex": {
-																											"margin_right": "4dp",
-																											"grow": 1
-																										}
-																									}
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"height": "2dp",
-																								"margin_left": "4dp"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"position_type": "absolute",
-																					"left": "0dp",
-																					"top": "10dp",
-																					"margin_top": "10dp",
-																					"right": "0dp",
-																					"height": "2dp",
-																					"width": "100%"
-																				}
-																			}
-																		}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"grow": 1
-																	}
-																}
-															}
-														},
-														{
-															"ak.somestring.Flexbox": {
-																"align_items": "flex_start",
-																"children": [
-																	{
-																		"ak.somestring.Flexbox": {
-																			"decoration": {
-																				"ak.somestring.BoxDecoration": {
-																					"corner_radius": "17dp"
-																				}
-																			},
-																			"children": [
-																				{
-																					"ls.components.Image": {
-																						"media_id": "10156395664922983",
-																						"height": 34,
-																						"width": 34,
-																						"_style": {
-																							"flex": {
-																								"width": "34dp",
-																								"height": "34dp"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"margin_right": "12dp",
-																					"width": "34dp",
-																					"height": "34dp"
-																				}
-																			}
-																		}
-																	},
-																	{
-																		"ak.somestring.Flexbox": {
-																			"flex_direction": "column",
-																			"align_items": "flex_start",
-																			"children": [
-																				{
-																					"ak.somestring.RichText": {
-																						"children": [
-																							{
-																								"ak.somestring.TextSpan": {
-																									"text": "eric",
-																									"text_size": "15sp",
-																									"text_style": "bold",
-																									"text_color": "#ffffff"
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"margin_bottom": "2dp",
-																								"width": "100%"
-																							}
-																						}
-																					}
-																				},
-																				{
-																					"ak.somestring.RichText": {
-																						"children": [
-																							{
-																								"ak.somestring.TextSpan": {
-																									"text": "20h",
-																									"text_size": "13sp",
-																									"text_style": "normal",
-																									"text_color": "#ffffff"
-																								}
-																							}
-																						],
-																						"_style": {
-																							"flex": {
-																								"width": "100%"
-																							}
-																						}
-																					}
-																				}
-																			],
-																			"_style": {
-																				"flex": {
-																					"width": "100%",
-																					"height": "100%"
-																				}
-																			}
-																		}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"position_type": "absolute",
-																		"top": "30dp",
-																		"left": "10dp",
-																		"height": "48dp"
-																	}
-																}
-															}
-														},
-														{
-															"ak.somestring.Flexbox": {
-																"children": [
-																	{
-																		"ls.components.StoriesReplyBar": {}
-																	}
-																],
-																"_style": {
-																	"flex": {
-																		"width": "100%",
-																		"height": "45dp",
-																		"margin_top": "auto",
-																		"margin_bottom": "auto"
-																	}
-																}
-															}
-														}
-													],
-													"_style": {
-														"flex": {
-															"position_type": "absolute",
-															"width": "100%",
-															"height": "100%",
-															"grow": 1
-														}
-													}
-												}
-											}
-										],
-										"_style": {
-											"flex": {
-												"width": "100%",
-												"height": "100%"
-											}
-										}
-									}
-								}
-							],
-							"_style": {
-								"flex": {
-									"height": "100%"
-								}
-							}
-						}
-					}
-				]
-			}
-		}
-	}
-}
diff --git a/srsly/tests/ujson/__init__.py b/srsly/tests/ujson/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/srsly/tests/ujson/test_ujson.py b/srsly/tests/ujson/test_ujson.py
deleted file mode 100644
index fac9a78..0000000
--- a/srsly/tests/ujson/test_ujson.py
+++ /dev/null
@@ -1,991 +0,0 @@
-import decimal
-import json
-import math
-import sys
-import unittest
-import pytest
-from io import StringIO
-from pathlib import Path
-from srsly import ujson
-
-
-json_unicode = json.dumps
-
-
-class UltraJSONTests(unittest.TestCase):
-    def test_encodeDecimal(self):
-        sut = decimal.Decimal("1337.1337")
-        encoded = ujson.encode(sut)
-        decoded = ujson.decode(encoded)
-        self.assertEqual(decoded, 1337.1337)
-
-    def test_encodeStringConversion(self):
-        input = "A string \\ / \b \f \n \r \t </script> &"
-        not_html_encoded = '"A string \\\\ \\/ \\b \\f \\n \\r \\t <\\/script> &"'
-        html_encoded = (
-            '"A string \\\\ \\/ \\b \\f \\n \\r \\t \\u003c\\/script\\u003e \\u0026"'
-        )
-        not_slashes_escaped = '"A string \\\\ / \\b \\f \\n \\r \\t </script> &"'
-
-        def helper(expected_output, **encode_kwargs):
-            output = ujson.encode(input, **encode_kwargs)
-            self.assertEqual(output, expected_output)
-            if encode_kwargs.get("escape_forward_slashes", True):
-                self.assertEqual(input, json.loads(output))
-                self.assertEqual(input, ujson.decode(output))
-
-        # Default behavior assumes encode_html_chars=False.
-        helper(not_html_encoded, ensure_ascii=True)
-        helper(not_html_encoded, ensure_ascii=False)
-
-        # Make sure explicit encode_html_chars=False works.
-        helper(not_html_encoded, ensure_ascii=True, encode_html_chars=False)
-        helper(not_html_encoded, ensure_ascii=False, encode_html_chars=False)
-
-        # Make sure explicit encode_html_chars=True does the encoding.
-        helper(html_encoded, ensure_ascii=True, encode_html_chars=True)
-        helper(html_encoded, ensure_ascii=False, encode_html_chars=True)
-
-        # Do escape forward slashes if disabled.
-        helper(not_slashes_escaped, escape_forward_slashes=False)
-
-    def testWriteEscapedString(self):
-        self.assertEqual(
-            "\"\\u003cimg src='\\u0026amp;'\\/\\u003e\"",
-            ujson.dumps("<img src='&amp;'/>", encode_html_chars=True),
-        )
-
-    def test_doubleLongIssue(self):
-        sut = {"a": -4342969734183514}
-        encoded = json.dumps(sut)
-        decoded = json.loads(encoded)
-        self.assertEqual(sut, decoded)
-        encoded = ujson.encode(sut)
-        decoded = ujson.decode(encoded)
-        self.assertEqual(sut, decoded)
-
-    def test_doubleLongDecimalIssue(self):
-        sut = {"a": -12345678901234.56789012}
-        encoded = json.dumps(sut)
-        decoded = json.loads(encoded)
-        self.assertEqual(sut, decoded)
-        encoded = ujson.encode(sut)
-        decoded = ujson.decode(encoded)
-        self.assertEqual(sut, decoded)
-
-    def test_encodeDecodeLongDecimal(self):
-        sut = {"a": -528656961.4399388}
-        encoded = ujson.dumps(sut)
-        ujson.decode(encoded)
-
-    def test_decimalDecodeTest(self):
-        sut = {"a": 4.56}
-        encoded = ujson.encode(sut)
-        decoded = ujson.decode(encoded)
-        self.assertAlmostEqual(sut[u"a"], decoded[u"a"])
-
-    def test_encodeDictWithUnicodeKeys(self):
-        input = {
-            "key1": "value1",
-            "key1": "value1",
-            "key1": "value1",
-            "key1": "value1",
-            "key1": "value1",
-            "key1": "value1",
-        }
-        ujson.encode(input)
-
-        input = {
-            "بن": "value1",
-            "بن": "value1",
-            "بن": "value1",
-            "بن": "value1",
-            "بن": "value1",
-            "بن": "value1",
-            "بن": "value1",
-        }
-        ujson.encode(input)
-
-    def test_encodeDoubleConversion(self):
-        input = math.pi
-        output = ujson.encode(input)
-        self.assertEqual(round(input, 5), round(json.loads(output), 5))
-        self.assertEqual(round(input, 5), round(ujson.decode(output), 5))
-
-    def test_encodeWithDecimal(self):
-        input = 1.0
-        output = ujson.encode(input)
-        self.assertEqual(output, "1.0")
-
-    def test_encodeDoubleNegConversion(self):
-        input = -math.pi
-        output = ujson.encode(input)
-
-        self.assertEqual(round(input, 5), round(json.loads(output), 5))
-        self.assertEqual(round(input, 5), round(ujson.decode(output), 5))
-
-    def test_encodeArrayOfNestedArrays(self):
-        input = [[[[]]]] * 20
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        # self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeArrayOfDoubles(self):
-        input = [31337.31337, 31337.31337, 31337.31337, 31337.31337] * 10
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        # self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeStringConversion2(self):
-        input = "A string \\ / \b \f \n \r \t"
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, '"A string \\\\ \\/ \\b \\f \\n \\r \\t"')
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_decodeUnicodeConversion(self):
-        pass
-
-    def test_encodeUnicodeConversion1(self):
-        input = "Räksmörgås اسامة بن محمد بن عوض بن لادن"
-        enc = ujson.encode(input)
-        dec = ujson.decode(enc)
-        self.assertEqual(enc, json_unicode(input))
-        self.assertEqual(dec, json.loads(enc))
-
-    def test_encodeControlEscaping(self):
-        input = "\x19"
-        enc = ujson.encode(input)
-        dec = ujson.decode(enc)
-        self.assertEqual(input, dec)
-        self.assertEqual(enc, json_unicode(input))
-
-    def test_encodeUnicodeConversion2(self):
-        input = "\xe6\x97\xa5\xd1\x88"
-        enc = ujson.encode(input)
-        dec = ujson.decode(enc)
-        self.assertEqual(enc, json_unicode(input))
-        self.assertEqual(dec, json.loads(enc))
-
-    def test_encodeUnicodeSurrogatePair(self):
-        input = "\xf0\x90\x8d\x86"
-        enc = ujson.encode(input)
-        dec = ujson.decode(enc)
-
-        self.assertEqual(enc, json_unicode(input))
-        self.assertEqual(dec, json.loads(enc))
-
-    def test_encodeUnicode4BytesUTF8(self):
-        input = "\xf0\x91\x80\xb0TRAILINGNORMAL"
-        enc = ujson.encode(input)
-        dec = ujson.decode(enc)
-
-        self.assertEqual(enc, json_unicode(input))
-        self.assertEqual(dec, json.loads(enc))
-
-    def test_encodeUnicode4BytesUTF8Highest(self):
-        input = "\xf3\xbf\xbf\xbfTRAILINGNORMAL"
-        enc = ujson.encode(input)
-        dec = ujson.decode(enc)
-
-        self.assertEqual(enc, json_unicode(input))
-        self.assertEqual(dec, json.loads(enc))
-
-    # Characters outside of Basic Multilingual Plane(larger than
-    # 16 bits) are represented as \UXXXXXXXX in python but should be encoded
-    # as \uXXXX\uXXXX in json.
-    def testEncodeUnicodeBMP(self):
-        s = "\U0001f42e\U0001f42e\U0001F42D\U0001F42D"  # 🐮🐮🐭🐭
-        encoded = ujson.dumps(s)
-        encoded_json = json.dumps(s)
-
-        if len(s) == 4:
-            self.assertEqual(len(encoded), len(s) * 12 + 2)
-        else:
-            self.assertEqual(len(encoded), len(s) * 6 + 2)
-
-        self.assertEqual(encoded, encoded_json)
-        decoded = ujson.loads(encoded)
-        self.assertEqual(s, decoded)
-
-        # ujson outputs an UTF-8 encoded str object
-        encoded = ujson.dumps(s, ensure_ascii=False)
-        # json outputs an unicode object
-        encoded_json = json.dumps(s, ensure_ascii=False)
-        self.assertEqual(len(encoded), len(s) + 2)  # original length + quotes
-        self.assertEqual(encoded, encoded_json)
-        decoded = ujson.loads(encoded)
-        self.assertEqual(s, decoded)
-
-    def testEncodeSymbols(self):
-        s = "\u273f\u2661\u273f"  # ✿♡✿
-        encoded = ujson.dumps(s)
-        encoded_json = json.dumps(s)
-        self.assertEqual(len(encoded), len(s) * 6 + 2)  # 6 characters + quotes
-        self.assertEqual(encoded, encoded_json)
-        decoded = ujson.loads(encoded)
-        self.assertEqual(s, decoded)
-
-        # ujson outputs an UTF-8 encoded str object
-        encoded = ujson.dumps(s, ensure_ascii=False)
-        # json outputs an unicode object
-        encoded_json = json.dumps(s, ensure_ascii=False)
-        self.assertEqual(len(encoded), len(s) + 2)  # original length + quotes
-        self.assertEqual(encoded, encoded_json)
-        decoded = ujson.loads(encoded)
-        self.assertEqual(s, decoded)
-
-    def test_encodeArrayInArray(self):
-        input = [[[[]]]]
-        output = ujson.encode(input)
-
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeIntConversion(self):
-        input = 31337
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeIntNegConversion(self):
-        input = -31337
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeLongNegConversion(self):
-        input = -9223372036854775808
-        output = ujson.encode(input)
-
-        json.loads(output)
-        ujson.decode(output)
-
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeListConversion(self):
-        input = [1, 2, 3, 4]
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeDictConversion(self):
-        input = {"k1": 1, "k2": 2, "k3": 3, "k4": 4}
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(input, ujson.decode(output))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeNoneConversion(self):
-        input = None
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeTrueConversion(self):
-        input = True
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeFalseConversion(self):
-        input = False
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeToUTF8(self):
-        input = b"\xe6\x97\xa5\xd1\x88"
-        input = input.decode("utf-8")
-        enc = ujson.encode(input, ensure_ascii=False)
-        dec = ujson.decode(enc)
-        self.assertEqual(enc, json.dumps(input, ensure_ascii=False))
-        self.assertEqual(dec, json.loads(enc))
-
-    def test_decodeFromUnicode(self):
-        input = '{"obj": 31337}'
-        dec1 = ujson.decode(input)
-        dec2 = ujson.decode(str(input))
-        self.assertEqual(dec1, dec2)
-
-    def test_encodeRecursionMax(self):
-        # 8 is the max recursion depth
-        class O2:
-            member = 0
-
-            def toDict(self):
-                return {"member": self.member}
-
-        class O1:
-            member = 0
-
-            def toDict(self):
-                return {"member": self.member}
-
-        input = O1()
-        input.member = O2()
-        input.member.member = input
-        self.assertRaises(OverflowError, ujson.encode, input)
-
-    def test_encodeDoubleNan(self):
-        input = float("nan")
-        self.assertRaises(OverflowError, ujson.encode, input)
-
-    def test_encodeDoubleInf(self):
-        input = float("inf")
-        self.assertRaises(OverflowError, ujson.encode, input)
-
-    def test_encodeDoubleNegInf(self):
-        input = -float("inf")
-        self.assertRaises(OverflowError, ujson.encode, input)
-
-    def test_encodeOrderedDict(self):
-        from collections import OrderedDict
-
-        input = OrderedDict([(1, 1), (0, 0), (8, 8), (2, 2)])
-        self.assertEqual('{"1":1,"0":0,"8":8,"2":2}', ujson.encode(input))
-
-    def test_decodeJibberish(self):
-        input = "fdsa sda v9sa fdsa"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeBrokenArrayStart(self):
-        input = "["
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeBrokenObjectStart(self):
-        input = "{"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeBrokenArrayEnd(self):
-        input = "]"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeArrayDepthTooBig(self):
-        input = "[" * (1024 * 1024)
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeBrokenObjectEnd(self):
-        input = "}"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeObjectTrailingCommaFail(self):
-        input = '{"one":1,}'
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeObjectDepthTooBig(self):
-        input = "{" * (1024 * 1024)
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeStringUnterminated(self):
-        input = '"TESTING'
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeStringUntermEscapeSequence(self):
-        input = '"TESTING\\"'
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeStringBadEscape(self):
-        input = '"TESTING\\"'
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeTrueBroken(self):
-        input = "tru"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeFalseBroken(self):
-        input = "fa"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeNullBroken(self):
-        input = "n"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeBrokenDictKeyTypeLeakTest(self):
-        input = '{{1337:""}}'
-        for x in range(1000):
-            self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeBrokenDictLeakTest(self):
-        input = '{{"key":"}'
-        for x in range(1000):
-            self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeBrokenListLeakTest(self):
-        input = "[[[true"
-        for x in range(1000):
-            self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeDictWithNoKey(self):
-        input = "{{{{31337}}}}"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeDictWithNoColonOrValue(self):
-        input = '{{{{"key"}}}}'
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeDictWithNoValue(self):
-        input = '{{{{"key":}}}}'
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeNumericIntPos(self):
-        input = "31337"
-        self.assertEqual(31337, ujson.decode(input))
-
-    def test_decodeNumericIntNeg(self):
-        input = "-31337"
-        self.assertEqual(-31337, ujson.decode(input))
-
-    def test_encodeUnicode4BytesUTF8Fail(self):
-        input = b"\xfd\xbf\xbf\xbf\xbf\xbf"
-        self.assertRaises(OverflowError, ujson.encode, input)
-
-    def test_encodeNullCharacter(self):
-        input = "31337 \x00 1337"
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-        input = "\x00"
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-        self.assertEqual('"  \\u0000\\r\\n "', ujson.dumps("  \u0000\r\n "))
-
-    def test_decodeNullCharacter(self):
-        input = '"31337 \\u0000 31337"'
-        self.assertEqual(ujson.decode(input), json.loads(input))
-
-    def test_encodeListLongConversion(self):
-        input = [
-            9223372036854775807,
-            9223372036854775807,
-            9223372036854775807,
-            9223372036854775807,
-            9223372036854775807,
-            9223372036854775807,
-        ]
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeListLongUnsignedConversion(self):
-        input = [18446744073709551615, 18446744073709551615, 18446744073709551615]
-        output = ujson.encode(input)
-
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeLongConversion(self):
-        input = 9223372036854775807
-        output = ujson.encode(input)
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_encodeLongUnsignedConversion(self):
-        input = 18446744073709551615
-        output = ujson.encode(input)
-
-        self.assertEqual(input, json.loads(output))
-        self.assertEqual(output, json.dumps(input))
-        self.assertEqual(input, ujson.decode(output))
-
-    def test_numericIntExp(self):
-        input = "1337E40"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_numericIntFrcExp(self):
-        input = "1.337E40"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_decodeNumericIntExpEPLUS(self):
-        input = "1337E+9"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_decodeNumericIntExpePLUS(self):
-        input = "1.337e+40"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_decodeNumericIntExpE(self):
-        input = "1337E40"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_decodeNumericIntExpe(self):
-        input = "1337e40"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_decodeNumericIntExpEMinus(self):
-        input = "1.337E-4"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_decodeNumericIntExpeMinus(self):
-        input = "1.337e-4"
-        output = ujson.decode(input)
-        self.assertEqual(output, json.loads(input))
-
-    def test_dumpToFile(self):
-        f = StringIO()
-        ujson.dump([1, 2, 3], f)
-        self.assertEqual("[1,2,3]", f.getvalue())
-
-    def test_dumpToFileLikeObject(self):
-        class filelike:
-            def __init__(self):
-                self.bytes = ""
-
-            def write(self, bytes):
-                self.bytes += bytes
-
-        f = filelike()
-        ujson.dump([1, 2, 3], f)
-        self.assertEqual("[1,2,3]", f.bytes)
-
-    def test_dumpFileArgsError(self):
-        self.assertRaises(TypeError, ujson.dump, [], "")
-
-    def test_loadFile(self):
-        f = StringIO("[1,2,3,4]")
-        self.assertEqual([1, 2, 3, 4], ujson.load(f))
-
-    def test_loadFileLikeObject(self):
-        class filelike:
-            def read(self):
-                try:
-                    self.end
-                except AttributeError:
-                    self.end = True
-                    return "[1,2,3,4]"
-
-        f = filelike()
-        self.assertEqual([1, 2, 3, 4], ujson.load(f))
-
-    def test_loadFileArgsError(self):
-        self.assertRaises(TypeError, ujson.load, "[]")
-
-    def test_encodeNumericOverflow(self):
-        self.assertRaises(OverflowError, ujson.encode, 12839128391289382193812939)
-
-    def test_decodeNumberWith32bitSignBit(self):
-        # Test that numbers that fit within 32 bits but would have the
-        # sign bit set (2**31 <= x < 2**32) are decoded properly.
-        docs = (
-            '{"id": 3590016419}',
-            '{"id": %s}' % 2 ** 31,
-            '{"id": %s}' % 2 ** 32,
-            '{"id": %s}' % ((2 ** 32) - 1),
-        )
-        results = (3590016419, 2 ** 31, 2 ** 32, 2 ** 32 - 1)
-        for doc, result in zip(docs, results):
-            self.assertEqual(ujson.decode(doc)["id"], result)
-
-    def test_encodeBigEscape(self):
-        for x in range(10):
-            base = "\u00e5".encode("utf-8")
-            input = base * 1024 * 1024 * 2
-            ujson.encode(input)
-
-    def test_decodeBigEscape(self):
-        for x in range(10):
-            base = "\u00e5".encode("utf-8")
-            quote = '"'.encode()
-            input = quote + (base * 1024 * 1024 * 2) + quote
-            ujson.decode(input)
-
-    def test_toDict(self):
-        d = {"key": 31337}
-
-        class DictTest:
-            def toDict(self):
-                return d
-
-            def __json__(self):
-                return '"json defined"'  # Fallback and shouldn't be called.
-
-        o = DictTest()
-        output = ujson.encode(o)
-        dec = ujson.decode(output)
-        self.assertEqual(dec, d)
-
-    def test_object_with_json(self):
-        # If __json__ returns a string, then that string
-        # will be used as a raw JSON snippet in the object.
-        output_text = "this is the correct output"
-
-        class JSONTest:
-            def __json__(self):
-                return '"' + output_text + '"'
-
-        d = {u"key": JSONTest()}
-        output = ujson.encode(d)
-        dec = ujson.decode(output)
-        self.assertEqual(dec, {u"key": output_text})
-
-    def test_object_with_json_unicode(self):
-        # If __json__ returns a string, then that string
-        # will be used as a raw JSON snippet in the object.
-        output_text = u"this is the correct output"
-
-        class JSONTest:
-            def __json__(self):
-                return u'"' + output_text + u'"'
-
-        d = {u"key": JSONTest()}
-        output = ujson.encode(d)
-        dec = ujson.decode(output)
-        self.assertEqual(dec, {u"key": output_text})
-
-    def test_object_with_complex_json(self):
-        # If __json__ returns a string, then that string
-        # will be used as a raw JSON snippet in the object.
-        obj = {u"foo": [u"bar", u"baz"]}
-
-        class JSONTest:
-            def __json__(self):
-                return ujson.encode(obj)
-
-        d = {u"key": JSONTest()}
-        output = ujson.encode(d)
-        dec = ujson.decode(output)
-        self.assertEqual(dec, {u"key": obj})
-
-    def test_object_with_json_type_error(self):
-        # __json__ must return a string, otherwise it should raise an error.
-        for return_value in (None, 1234, 12.34, True, {}):
-
-            class JSONTest:
-                def __json__(self):
-                    return return_value
-
-            d = {u"key": JSONTest()}
-            self.assertRaises(TypeError, ujson.encode, d)
-
-    def test_object_with_json_attribute_error(self):
-        # If __json__ raises an error, make sure python actually raises it.
-        class JSONTest:
-            def __json__(self):
-                raise AttributeError
-
-        d = {u"key": JSONTest()}
-        self.assertRaises(AttributeError, ujson.encode, d)
-
-    def test_decodeArrayTrailingCommaFail(self):
-        input = "[31337,]"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeArrayLeadingCommaFail(self):
-        input = "[,31337]"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeArrayOnlyCommaFail(self):
-        input = "[,]"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeArrayUnmatchedBracketFail(self):
-        input = "[]]"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeArrayEmpty(self):
-        input = "[]"
-        obj = ujson.decode(input)
-        self.assertEqual([], obj)
-
-    def test_decodeArrayOneItem(self):
-        input = "[31337]"
-        ujson.decode(input)
-
-    def test_decodeLongUnsignedValue(self):
-        input = "18446744073709551615"
-        ujson.decode(input)
-
-    def test_decodeBigValue(self):
-        input = "9223372036854775807"
-        ujson.decode(input)
-
-    def test_decodeSmallValue(self):
-        input = "-9223372036854775808"
-        ujson.decode(input)
-
-    def test_decodeTooBigValue(self):
-        input = "18446744073709551616"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeTooSmallValue(self):
-        input = "-90223372036854775809"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeVeryTooBigValue(self):
-        input = "18446744073709551616"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeVeryTooSmallValue(self):
-        input = "-90223372036854775809"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeWithTrailingWhitespaces(self):
-        input = "{}\n\t "
-        ujson.decode(input)
-
-    def test_decodeWithTrailingNonWhitespaces(self):
-        input = "{}\n\t a"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeArrayWithBigInt(self):
-        input = "[18446744073709551616]"
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_decodeFloatingPointAdditionalTests(self):
-        self.assertAlmostEqual(-1.1234567893, ujson.loads("-1.1234567893"))
-        self.assertAlmostEqual(-1.234567893, ujson.loads("-1.234567893"))
-        self.assertAlmostEqual(-1.34567893, ujson.loads("-1.34567893"))
-        self.assertAlmostEqual(-1.4567893, ujson.loads("-1.4567893"))
-        self.assertAlmostEqual(-1.567893, ujson.loads("-1.567893"))
-        self.assertAlmostEqual(-1.67893, ujson.loads("-1.67893"))
-        self.assertAlmostEqual(-1.7894, ujson.loads("-1.7894"))
-        self.assertAlmostEqual(-1.893, ujson.loads("-1.893"))
-        self.assertAlmostEqual(-1.3, ujson.loads("-1.3"))
-
-        self.assertAlmostEqual(1.1234567893, ujson.loads("1.1234567893"))
-        self.assertAlmostEqual(1.234567893, ujson.loads("1.234567893"))
-        self.assertAlmostEqual(1.34567893, ujson.loads("1.34567893"))
-        self.assertAlmostEqual(1.4567893, ujson.loads("1.4567893"))
-        self.assertAlmostEqual(1.567893, ujson.loads("1.567893"))
-        self.assertAlmostEqual(1.67893, ujson.loads("1.67893"))
-        self.assertAlmostEqual(1.7894, ujson.loads("1.7894"))
-        self.assertAlmostEqual(1.893, ujson.loads("1.893"))
-        self.assertAlmostEqual(1.3, ujson.loads("1.3"))
-
-    def test_ReadBadObjectSyntax(self):
-        input = '{"age", 44}'
-        self.assertRaises(ValueError, ujson.decode, input)
-
-    def test_ReadTrue(self):
-        self.assertEqual(True, ujson.loads("true"))
-
-    def test_ReadFalse(self):
-        self.assertEqual(False, ujson.loads("false"))
-
-    def test_ReadNull(self):
-        self.assertEqual(None, ujson.loads("null"))
-
-    def test_WriteTrue(self):
-        self.assertEqual("true", ujson.dumps(True))
-
-    def test_WriteFalse(self):
-        self.assertEqual("false", ujson.dumps(False))
-
-    def test_WriteNull(self):
-        self.assertEqual("null", ujson.dumps(None))
-
-    def test_ReadArrayOfSymbols(self):
-        self.assertEqual([True, False, None], ujson.loads(" [ true, false,null] "))
-
-    def test_WriteArrayOfSymbolsFromList(self):
-        self.assertEqual("[true,false,null]", ujson.dumps([True, False, None]))
-
-    def test_WriteArrayOfSymbolsFromTuple(self):
-        self.assertEqual("[true,false,null]", ujson.dumps((True, False, None)))
-
-    def test_encodingInvalidUnicodeCharacter(self):
-        s = "\udc7f"
-        self.assertRaises(UnicodeEncodeError, ujson.dumps, s)
-
-    def test_sortKeys(self):
-        data = {"a": 1, "c": 1, "b": 1, "e": 1, "f": 1, "d": 1}
-        sortedKeys = ujson.dumps(data, sort_keys=True)
-        self.assertEqual(sortedKeys, '{"a":1,"b":1,"c":1,"d":1,"e":1,"f":1}')
-
-    @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount")
-    def test_does_not_leak_dictionary_values(self):
-        import gc
-
-        gc.collect()
-        value = ["abc"]
-        data = {"1": value}
-        ref_count = sys.getrefcount(value)
-        ujson.dumps(data)
-        self.assertEqual(ref_count, sys.getrefcount(value))
-
-    @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount")
-    def test_does_not_leak_dictionary_keys(self):
-        import gc
-
-        gc.collect()
-        key1 = "1"
-        key2 = "1"
-        value1 = ["abc"]
-        value2 = [1, 2, 3]
-        data = {key1: value1, key2: value2}
-        ref_count1 = sys.getrefcount(key1)
-        ref_count2 = sys.getrefcount(key2)
-        ujson.dumps(data)
-        self.assertEqual(ref_count1, sys.getrefcount(key1))
-        self.assertEqual(ref_count2, sys.getrefcount(key2))
-
-    @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount")
-    def test_does_not_leak_dictionary_string_key(self):
-        import gc
-
-        gc.collect()
-        key1 = "1"
-        value1 = 1
-        data = {key1: value1}
-        ref_count1 = sys.getrefcount(key1)
-        ujson.dumps(data)
-        self.assertEqual(ref_count1, sys.getrefcount(key1))
-
-    @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount")
-    def test_does_not_leak_dictionary_tuple_key(self):
-        import gc
-
-        gc.collect()
-        key1 = ("a",)
-        value1 = 1
-        data = {key1: value1}
-        ref_count1 = sys.getrefcount(key1)
-        ujson.dumps(data)
-        self.assertEqual(ref_count1, sys.getrefcount(key1))
-
-    @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount")
-    def test_does_not_leak_dictionary_bytes_key(self):
-        import gc
-
-        gc.collect()
-        key1 = b"1"
-        value1 = 1
-        data = {key1: value1}
-        ref_count1 = sys.getrefcount(key1)
-        ujson.dumps(data)
-        self.assertEqual(ref_count1, sys.getrefcount(key1))
-
-    @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount")
-    def test_does_not_leak_dictionary_None_key(self):
-        import gc
-
-        gc.collect()
-        key1 = None
-        value1 = 1
-        data = {key1: value1}
-        ref_count1 = sys.getrefcount(key1)
-        ujson.dumps(data)
-        self.assertEqual(ref_count1, sys.getrefcount(key1))
-
-
-"""
-def test_decodeNumericIntFrcOverflow(self):
-input = "X.Y"
-raise NotImplementedError("Implement this test!")
-
-
-def test_decodeStringUnicodeEscape(self):
-input = "\u3131"
-raise NotImplementedError("Implement this test!")
-
-def test_decodeStringUnicodeBrokenEscape(self):
-input = "\u3131"
-raise NotImplementedError("Implement this test!")
-
-def test_decodeStringUnicodeInvalidEscape(self):
-input = "\u3131"
-raise NotImplementedError("Implement this test!")
-
-def test_decodeStringUTF8(self):
-input = "someutfcharacters"
-raise NotImplementedError("Implement this test!")
-
-"""
-
-if __name__ == "__main__":
-    unittest.main()
-
-"""
-# Use this to look for memory leaks
-if __name__ == '__main__':
-    from guppy import hpy
-    hp = hpy()
-    hp.setrelheap()
-    while True:
-        try:
-            unittest.main()
-        except SystemExit:
-            pass
-        heap = hp.heapu()
-        print(heap)
-"""
-
-
-@pytest.mark.parametrize("indent", list(range(65537, 65542)))
-def test_dump_huge_indent(indent):
-    ujson.encode({"a": True}, indent=indent)
-
-
-@pytest.mark.parametrize("first_length", list(range(2, 7)))
-@pytest.mark.parametrize("second_length", list(range(10919, 10924)))
-def test_dump_long_string(first_length, second_length):
-    ujson.dumps(["a" * first_length, "\x00" * second_length])
-
-
-def test_dump_indented_nested_list():
-    a = _a = []
-    for i in range(20):
-        _a.append(list(range(i)))
-        _a = _a[-1]
-        ujson.dumps(a, indent=i)
-
-
-@pytest.mark.parametrize("indent", [0, 1, 2, 4, 5, 8, 49])
-def test_issue_334(indent):
-    path = Path(__file__).with_name("334-reproducer.json")
-    a = ujson.loads(path.read_bytes())
-    ujson.dumps(a, indent=indent)
-
-
-@pytest.mark.parametrize(
-    "test_input, expected",
-    [
-        # Normal cases
-        (r'"\uD83D\uDCA9"', "\U0001F4A9"),
-        (r'"a\uD83D\uDCA9b"', "a\U0001F4A9b"),
-        # Unpaired surrogates
-        (r'"\uD800"', "\uD800"),
-        (r'"a\uD800b"', "a\uD800b"),
-        (r'"\uDEAD"', "\uDEAD"),
-        (r'"a\uDEADb"', "a\uDEADb"),
-        (r'"\uD83D\uD83D\uDCA9"', "\uD83D\U0001F4A9"),
-        (r'"\uDCA9\uD83D\uDCA9"', "\uDCA9\U0001F4A9"),
-        (r'"\uD83D\uDCA9\uD83D"', "\U0001F4A9\uD83D"),
-        (r'"\uD83D\uDCA9\uDCA9"', "\U0001F4A9\uDCA9"),
-        (r'"\uD83D \uDCA9"', "\uD83D \uDCA9"),
-        # No decoding of actual surrogate characters (rather than escaped ones)
-        ('"\uD800"', "\uD800"),
-        ('"\uDEAD"', "\uDEAD"),
-        ('"\uD800a\uDEAD"', "\uD800a\uDEAD"),
-        ('"\uD83D\uDCA9"', "\uD83D\uDCA9"),
-    ],
-)
-def test_decode_surrogate_characters(test_input, expected):
-    assert ujson.loads(test_input) == expected
-    assert ujson.loads(test_input.encode("utf-8", "surrogatepass")) == expected
-
-    # Ensure that this matches stdlib's behaviour
-    assert json.loads(test_input) == expected
diff --git a/srsly/ujson/JSONtoObj.c b/srsly/ujson/JSONtoObj.c
deleted file mode 100644
index 8563970..0000000
--- a/srsly/ujson/JSONtoObj.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
- * Copyright (c) 1988-1993 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-#include "py_defines.h"
-#include <ultrajson.h>
-
-
-//#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__)
-#define PRINTMARK()
-
-void Object_objectAddKey(void *prv, JSOBJ obj, JSOBJ name, JSOBJ value)
-{
-  PyDict_SetItem (obj, name, value);
-  Py_DECREF( (PyObject *) name);
-  Py_DECREF( (PyObject *) value);
-  return;
-}
-
-void Object_arrayAddItem(void *prv, JSOBJ obj, JSOBJ value)
-{
-  PyList_Append(obj, value);
-  Py_DECREF( (PyObject *) value);
-  return;
-}
-
-/*
-Check that Py_UCS4 is the same as JSUINT32, else Object_newString will fail.
-Based on Linux's check in vbox_vmmdev_types.h.
-This should be replaced with
-  _Static_assert(sizeof(Py_UCS4) == sizeof(JSUINT32));
-when C11 is made mandatory (CPython 3.11+, PyPy ?).
-*/
-typedef char assert_py_ucs4_is_jsuint32[1 - 2*!(sizeof(Py_UCS4) == sizeof(JSUINT32))];
-
-static JSOBJ Object_newString(void *prv, JSUINT32 *start, JSUINT32 *end)
-{
-  return PyUnicode_FromKindAndData (PyUnicode_4BYTE_KIND, (Py_UCS4 *) start, (end - start));
-}
-
-JSOBJ Object_newTrue(void *prv)
-{
-  Py_RETURN_TRUE;
-}
-
-JSOBJ Object_newFalse(void *prv)
-{
-  Py_RETURN_FALSE;
-}
-
-JSOBJ Object_newNull(void *prv)
-{
-  Py_RETURN_NONE;
-}
-
-JSOBJ Object_newObject(void *prv)
-{
-  return PyDict_New();
-}
-
-JSOBJ Object_newArray(void *prv)
-{
-  return PyList_New(0);
-}
-
-JSOBJ Object_newInteger(void *prv, JSINT32 value)
-{
-  return PyInt_FromLong( (long) value);
-}
-
-JSOBJ Object_newLong(void *prv, JSINT64 value)
-{
-  return PyLong_FromLongLong (value);
-}
-
-JSOBJ Object_newUnsignedLong(void *prv, JSUINT64 value)
-{
-  return PyLong_FromUnsignedLongLong (value);
-}
-
-JSOBJ Object_newDouble(void *prv, double value)
-{
-  return PyFloat_FromDouble(value);
-}
-
-static void Object_releaseObject(void *prv, JSOBJ obj)
-{
-  Py_DECREF( ((PyObject *)obj));
-}
-
-static char *g_kwlist[] = {"obj", "precise_float", NULL};
-
-PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs)
-{
-  PyObject *ret;
-  PyObject *sarg;
-  PyObject *arg;
-  PyObject *opreciseFloat = NULL;
-  JSONObjectDecoder decoder =
-  {
-    Object_newString,
-    Object_objectAddKey,
-    Object_arrayAddItem,
-    Object_newTrue,
-    Object_newFalse,
-    Object_newNull,
-    Object_newObject,
-    Object_newArray,
-    Object_newInteger,
-    Object_newLong,
-    Object_newUnsignedLong,
-    Object_newDouble,
-    Object_releaseObject,
-    PyObject_Malloc,
-    PyObject_Free,
-    PyObject_Realloc
-  };
-
-  decoder.preciseFloat = 0;
-  decoder.prv = NULL;
-
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", g_kwlist, &arg, &opreciseFloat))
-  {
-      return NULL;
-  }
-
-  if (opreciseFloat && PyObject_IsTrue(opreciseFloat))
-  {
-      decoder.preciseFloat = 1;
-  }
-
-  if (PyString_Check(arg))
-  {
-      sarg = arg;
-  }
-  else
-  if (PyUnicode_Check(arg))
-  {
-    sarg = PyUnicode_AsEncodedString(arg, NULL, "surrogatepass");
-    if (sarg == NULL)
-    {
-      //Exception raised above us by codec according to docs
-      return NULL;
-    }
-  }
-  else
-  {
-    PyErr_Format(PyExc_TypeError, "Expected String or Unicode");
-    return NULL;
-  }
-
-  decoder.errorStr = NULL;
-  decoder.errorOffset = NULL;
-
-  ret = JSON_DecodeObject(&decoder, PyString_AS_STRING(sarg), PyString_GET_SIZE(sarg));
-
-  if (sarg != arg)
-  {
-    Py_DECREF(sarg);
-  }
-
-  if (decoder.errorStr)
-  {
-    /*
-    FIXME: It's possible to give a much nicer error message here with actual failing element in input etc*/
-
-    PyErr_Format (PyExc_ValueError, "%s", decoder.errorStr);
-
-    if (ret)
-    {
-        Py_DECREF( (PyObject *) ret);
-    }
-
-    return NULL;
-  }
-
-  return ret;
-}
-
-PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs)
-{
-  PyObject *read;
-  PyObject *string;
-  PyObject *result;
-  PyObject *file = NULL;
-  PyObject *argtuple;
-
-  if (!PyArg_ParseTuple (args, "O", &file))
-  {
-    return NULL;
-  }
-
-  if (!PyObject_HasAttrString (file, "read"))
-  {
-    PyErr_Format (PyExc_TypeError, "expected file");
-    return NULL;
-  }
-
-  read = PyObject_GetAttrString (file, "read");
-
-  if (!PyCallable_Check (read)) {
-    Py_XDECREF(read);
-    PyErr_Format (PyExc_TypeError, "expected file");
-    return NULL;
-  }
-
-  string = PyObject_CallObject (read, NULL);
-  Py_XDECREF(read);
-
-  if (string == NULL)
-  {
-    return NULL;
-  }
-
-  argtuple = PyTuple_Pack(1, string);
-
-  result = JSONToObj (self, argtuple, kwargs);
-
-  Py_XDECREF(argtuple);
-  Py_XDECREF(string);
-
-  if (result == NULL) {
-    return NULL;
-  }
-
-  return result;
-}
diff --git a/srsly/ujson/__init__.py b/srsly/ujson/__init__.py
deleted file mode 100644
index 744ff70..0000000
--- a/srsly/ujson/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .ujson import decode, encode, dump, dumps, load, loads  # noqa: F401
diff --git a/srsly/ujson/lib/dconv_wrapper.cc b/srsly/ujson/lib/dconv_wrapper.cc
deleted file mode 100644
index 27e1b9b..0000000
--- a/srsly/ujson/lib/dconv_wrapper.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-#include "double-conversion.h"
-
-namespace double_conversion
-{
-  static StringToDoubleConverter* s2d_instance = NULL;
-  static DoubleToStringConverter* d2s_instance = NULL;
-
-  extern "C"
-  {
-    void dconv_d2s_init(int flags,
-                        const char* infinity_symbol,
-                        const char* nan_symbol,
-                        char exponent_character,
-                        int decimal_in_shortest_low,
-                        int decimal_in_shortest_high,
-                        int max_leading_padding_zeroes_in_precision_mode,
-                        int max_trailing_padding_zeroes_in_precision_mode)
-    {
-        d2s_instance = new DoubleToStringConverter(flags, infinity_symbol, nan_symbol,
-                                        exponent_character, decimal_in_shortest_low,
-                                        decimal_in_shortest_high, max_leading_padding_zeroes_in_precision_mode,
-                                        max_trailing_padding_zeroes_in_precision_mode);
-    }
-
-    int dconv_d2s(double value, char* buf, int buflen, int* strlength)
-    {
-        StringBuilder sb(buf, buflen);
-        int success =  static_cast<int>(d2s_instance->ToShortest(value, &sb));
-        *strlength = success ? sb.position() : -1;
-        return success;
-    }
-
-    void dconv_d2s_free()
-    {
-        delete d2s_instance;
-        d2s_instance = NULL;
-    }
-
-    void dconv_s2d_init(int flags, double empty_string_value, 
-                        double junk_string_value, const char* infinity_symbol,
-                        const char* nan_symbol)
-    {
-        s2d_instance = new StringToDoubleConverter(flags, empty_string_value,
-                            junk_string_value, infinity_symbol, nan_symbol);
-    }
-
-    double dconv_s2d(const char* buffer, int length, int* processed_characters_count)
-    {
-        return s2d_instance->StringToDouble(buffer, length, processed_characters_count);
-    }
-
-    void dconv_s2d_free()
-    {
-        delete s2d_instance;
-        s2d_instance = NULL;
-    }
-  }
-}
diff --git a/srsly/ujson/lib/ultrajson.h b/srsly/ujson/lib/ultrajson.h
deleted file mode 100644
index a117901..0000000
--- a/srsly/ujson/lib/ultrajson.h
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
- * Copyright (c) 1988-1993 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-/*
-Ultra fast JSON encoder and decoder
-Developed by Jonas Tarnstrom (jonas@esn.me).
-
-Encoder notes:
-------------------
-
-:: Cyclic references ::
-Cyclic referenced objects are not detected.
-Set JSONObjectEncoder.recursionMax to suitable value or make sure input object
-tree doesn't have cyclic references.
-
-*/
-
-#ifndef __ULTRAJSON_H__
-#define __ULTRAJSON_H__
-
-#include <stdio.h>
-
-// Max decimals to encode double floating point numbers with
-#ifndef JSON_DOUBLE_MAX_DECIMALS
-#define JSON_DOUBLE_MAX_DECIMALS 15
-#endif
-
-// Max recursion depth, default for encoder
-#ifndef JSON_MAX_RECURSION_DEPTH
-#define JSON_MAX_RECURSION_DEPTH 1024
-#endif
-
-// Max recursion depth, default for decoder
-#ifndef JSON_MAX_OBJECT_DEPTH
-#define JSON_MAX_OBJECT_DEPTH 1024
-#endif
-
-/*
-Dictates and limits how much stack space for buffers UltraJSON will use before resorting to provided heap functions */
-#ifndef JSON_MAX_STACK_BUFFER_SIZE
-#define JSON_MAX_STACK_BUFFER_SIZE 131072
-#endif
-
-#ifdef _WIN32
-
-typedef __int64 JSINT64;
-typedef unsigned __int64 JSUINT64;
-
-typedef __int32 JSINT32;
-typedef unsigned __int32 JSUINT32;
-typedef unsigned __int8 JSUINT8;
-typedef unsigned __int16 JSUTF16;
-typedef unsigned __int32 JSUTF32;
-typedef __int64 JSLONG;
-
-#define EXPORTFUNCTION __declspec(dllexport)
-
-#define FASTCALL_MSVC __fastcall
-#define FASTCALL_ATTR
-#define INLINE_PREFIX __inline
-
-#else
-
-#include <stdint.h>
-typedef int64_t JSINT64;
-typedef uint64_t JSUINT64;
-
-typedef int32_t JSINT32;
-typedef uint32_t JSUINT32;
-
-#define FASTCALL_MSVC
-
-#if !defined __x86_64__
-#define FASTCALL_ATTR __attribute__((fastcall))
-#else
-#define FASTCALL_ATTR
-#endif
-
-#define INLINE_PREFIX inline
-
-typedef uint8_t JSUINT8;
-typedef uint16_t JSUTF16;
-typedef uint32_t JSUTF32;
-
-typedef int64_t JSLONG;
-
-#define EXPORTFUNCTION
-#endif
-
-#if !(defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__))
-
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#define __LITTLE_ENDIAN__
-#else
-
-#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-#define __BIG_ENDIAN__
-#endif
-
-#endif
-
-#endif
-
-#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
-#error "Endianess not supported"
-#endif
-
-enum JSTYPES
-{
-  JT_NULL,      // NULL
-  JT_TRUE,      // boolean true
-  JT_FALSE,     // boolean false
-  JT_INT,       // (JSINT32 (signed 32-bit))
-  JT_LONG,      // (JSINT64 (signed 64-bit))
-  JT_ULONG,     // (JSUINT64 (unsigned 64-bit))
-  JT_DOUBLE,    // (double)
-  JT_UTF8,      // (char 8-bit)
-  JT_RAW,       // (raw char 8-bit)
-  JT_ARRAY,     // Array structure
-  JT_OBJECT,    // Key/Value structure
-  JT_INVALID,   // Internal, do not return nor expect
-};
-
-typedef void * JSOBJ;
-typedef void * JSITER;
-
-typedef struct __JSONTypeContext
-{
-  int type;
-  void *prv;
-  void *encoder_prv;
-} JSONTypeContext;
-
-/*
-Function pointer declarations, suitable for implementing UltraJSON */
-typedef int (*JSPFN_ITERNEXT)(JSOBJ obj, JSONTypeContext *tc);
-typedef void (*JSPFN_ITEREND)(JSOBJ obj, JSONTypeContext *tc);
-typedef JSOBJ (*JSPFN_ITERGETVALUE)(JSOBJ obj, JSONTypeContext *tc);
-typedef char *(*JSPFN_ITERGETNAME)(JSOBJ obj, JSONTypeContext *tc, size_t *outLen);
-typedef void *(*JSPFN_MALLOC)(size_t size);
-typedef void (*JSPFN_FREE)(void *pptr);
-typedef void *(*JSPFN_REALLOC)(void *base, size_t size);
-
-
-struct __JSONObjectEncoder;
-
-typedef struct __JSONObjectEncoder
-{
-  void (*beginTypeContext)(JSOBJ obj, JSONTypeContext *tc, struct __JSONObjectEncoder *enc);
-  void (*endTypeContext)(JSOBJ obj, JSONTypeContext *tc);
-  const char *(*getStringValue)(JSOBJ obj, JSONTypeContext *tc, size_t *_outLen);
-  JSINT64 (*getLongValue)(JSOBJ obj, JSONTypeContext *tc);
-  JSUINT64 (*getUnsignedLongValue)(JSOBJ obj, JSONTypeContext *tc);
-  JSINT32 (*getIntValue)(JSOBJ obj, JSONTypeContext *tc);
-  double (*getDoubleValue)(JSOBJ obj, JSONTypeContext *tc);
-
-  /*
-  Retrieve next object in an iteration. Should return 0 to indicate iteration has reached end or 1 if there are more items.
-  Implementor is responsible for keeping state of the iteration. Use ti->prv fields for this
-  */
-  JSPFN_ITERNEXT iterNext;
-
-  /*
-  Ends the iteration of an iteratable object.
-  Any iteration state stored in ti->prv can be freed here
-  */
-  JSPFN_ITEREND iterEnd;
-
-  /*
-  Returns a reference to the value object of an iterator
-  The is responsible for the life-cycle of the returned string. Use iterNext/iterEnd and ti->prv to keep track of current object
-  */
-  JSPFN_ITERGETVALUE iterGetValue;
-
-  /*
-  Return name of iterator.
-  The is responsible for the life-cycle of the returned string. Use iterNext/iterEnd and ti->prv to keep track of current object
-  */
-  JSPFN_ITERGETNAME iterGetName;
-
-  /*
-  Release a value as indicated by setting ti->release = 1 in the previous getValue call.
-  The ti->prv array should contain the necessary context to release the value
-  */
-  void (*releaseObject)(JSOBJ obj);
-
-  /* Library functions
-  Set to NULL to use STDLIB malloc,realloc,free */
-  JSPFN_MALLOC malloc;
-  JSPFN_REALLOC realloc;
-  JSPFN_FREE free;
-
-  /*
-  Configuration for max recursion, set to 0 to use default (see JSON_MAX_RECURSION_DEPTH)*/
-  int recursionMax;
-
-  /*
-  Configuration for max decimals of double floating point numbers to encode (0-9) */
-  int doublePrecision;
-
-  /*
-  If true output will be ASCII with all characters above 127 encoded as \uXXXX. If false output will be UTF-8 or what ever charset strings are brought as */
-  int forceASCII;
-
-  /*
-  If true, '<', '>', and '&' characters will be encoded as \u003c, \u003e, and \u0026, respectively. If false, no special encoding will be used. */
-  int encodeHTMLChars;
-
-  /*
-  If true, '/' will be encoded as \/. If false, no escaping. */
-  int escapeForwardSlashes;
-
-  /*
-  If true, dictionaries are iterated through in sorted key order. */
-  int sortKeys;
-
-  /*
-  Configuration for spaces of indent */
-  int indent;
-
-  /*
-  Private pointer to be used by the caller. Passed as encoder_prv in JSONTypeContext */
-  void *prv;
-
-  /*
-  Set to an error message if error occured */
-  const char *errorMsg;
-  JSOBJ errorObj;
-
-  /* Buffer stuff */
-  char *start;
-  char *offset;
-  char *end;
-  int heap;
-  int level;
-
-} JSONObjectEncoder;
-
-
-/*
-Encode an object structure into JSON.
-
-Arguments:
-obj - An anonymous type representing the object
-enc - Function definitions for querying JSOBJ type
-buffer - Preallocated buffer to store result in. If NULL function allocates own buffer
-cbBuffer - Length of buffer (ignored if buffer is NULL)
-
-Returns:
-Encoded JSON object as a null terminated char string.
-
-NOTE:
-If the supplied buffer wasn't enough to hold the result the function will allocate a new buffer.
-Life cycle of the provided buffer must still be handled by caller.
-
-If the return value doesn't equal the specified buffer caller must release the memory using
-JSONObjectEncoder.free or free() as specified when calling this function.
-*/
-EXPORTFUNCTION char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *buffer, size_t cbBuffer);
-
-
-
-typedef struct __JSONObjectDecoder
-{
-  JSOBJ (*newString)(void *prv, JSUINT32 *start, JSUINT32 *end);
-  void (*objectAddKey)(void *prv, JSOBJ obj, JSOBJ name, JSOBJ value);
-  void (*arrayAddItem)(void *prv, JSOBJ obj, JSOBJ value);
-  JSOBJ (*newTrue)(void *prv);
-  JSOBJ (*newFalse)(void *prv);
-  JSOBJ (*newNull)(void *prv);
-  JSOBJ (*newObject)(void *prv);
-  JSOBJ (*newArray)(void *prv);
-  JSOBJ (*newInt)(void *prv, JSINT32 value);
-  JSOBJ (*newLong)(void *prv, JSINT64 value);
-  JSOBJ (*newUnsignedLong)(void *prv, JSUINT64 value);
-  JSOBJ (*newDouble)(void *prv, double value);
-  void (*releaseObject)(void *prv, JSOBJ obj);
-  JSPFN_MALLOC malloc;
-  JSPFN_FREE free;
-  JSPFN_REALLOC realloc;
-  char *errorStr;
-  char *errorOffset;
-  int preciseFloat;
-  void *prv;
-} JSONObjectDecoder;
-
-EXPORTFUNCTION JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuffer);
-
-#endif
diff --git a/srsly/ujson/lib/ultrajsondec.c b/srsly/ujson/lib/ultrajsondec.c
deleted file mode 100644
index a88a008..0000000
--- a/srsly/ujson/lib/ultrajsondec.c
+++ /dev/null
@@ -1,891 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
-* Copyright (c) 1988-1993 The Regents of the University of California.
-* Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-#include "ultrajson.h"
-#include <math.h>
-#include <assert.h>
-#include <string.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-struct DecoderState
-{
-  char *start;
-  char *end;
-  JSUINT32 *escStart;
-  JSUINT32 *escEnd;
-  int escHeap;
-  int lastType;
-  JSUINT32 objDepth;
-  void *prv;
-  JSONObjectDecoder *dec;
-};
-
-JSOBJ FASTCALL_MSVC decode_any( struct DecoderState *ds) FASTCALL_ATTR;
-typedef JSOBJ (*PFN_DECODER)( struct DecoderState *ds);
-
-static JSOBJ SetError( struct DecoderState *ds, int offset, const char *message)
-{
-  ds->dec->errorOffset = ds->start + offset;
-  ds->dec->errorStr = (char *) message;
-  return NULL;
-}
-
-double createDouble(double intNeg, double intValue, double frcValue, int frcDecimalCount)
-{
-  static const double g_pow10[] = {1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001,0.0000001, 0.00000001, 0.000000001, 0.0000000001, 0.00000000001, 0.000000000001, 0.0000000000001, 0.00000000000001, 0.000000000000001};
-  return (intValue + (frcValue * g_pow10[frcDecimalCount])) * intNeg;
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decodePreciseFloat(struct DecoderState *ds)
-{
-  char *end;
-  double value;
-  errno = 0;
-
-  value = strtod(ds->start, &end);
-
-  if (errno == ERANGE)
-  {
-    return SetError(ds, -1, "Range error when decoding numeric as double");
-  }
-
-  ds->start = end;
-  return ds->dec->newDouble(ds->prv, value);
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_numeric (struct DecoderState *ds)
-{
-  int intNeg = 1;
-  int mantSize = 0;
-  JSUINT64 intValue;
-  JSUINT64 prevIntValue;
-  int chr;
-  int decimalCount = 0;
-  double frcValue = 0.0;
-  double expNeg;
-  double expValue;
-  char *offset = ds->start;
-
-  JSUINT64 overflowLimit = LLONG_MAX;
-
-  if (*(offset) == '-')
-  {
-    offset ++;
-    intNeg = -1;
-    overflowLimit = LLONG_MIN;
-  }
-
-  // Scan integer part
-  intValue = 0;
-
-  while (1)
-  {
-    chr = (int) (unsigned char) *(offset);
-
-    switch (chr)
-    {
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-      {
-        //PERF: Don't do 64-bit arithmetic here unless we know we have to
-        prevIntValue = intValue;
-        intValue = intValue * 10ULL + (JSLONG) (chr - 48);
-
-        if (intNeg == 1 && prevIntValue > intValue)
-        {
-          return SetError(ds, -1, "Value is too big!");
-        }
-        else if (intNeg == -1 && intValue > overflowLimit)
-        {
-          return SetError(ds, -1, overflowLimit == LLONG_MAX ? "Value is too big!" : "Value is too small");
-        }
-
-        offset ++;
-        mantSize ++;
-        break;
-      }
-      case '.':
-      {
-        offset ++;
-        goto DECODE_FRACTION;
-        break;
-      }
-      case 'e':
-      case 'E':
-      {
-        offset ++;
-        goto DECODE_EXPONENT;
-        break;
-      }
-
-      default:
-      {
-        goto BREAK_INT_LOOP;
-        break;
-      }
-    }
-  }
-
-BREAK_INT_LOOP:
-
-  ds->lastType = JT_INT;
-  ds->start = offset;
-
-  if (intNeg == 1 && (intValue & 0x8000000000000000ULL) != 0)
-  {
-    return ds->dec->newUnsignedLong(ds->prv, intValue);
-  }
-  else if ((intValue >> 31))
-  {
-    return ds->dec->newLong(ds->prv, (JSINT64) (intValue * (JSINT64) intNeg));
-  }
-  else
-  {
-    return ds->dec->newInt(ds->prv, (JSINT32) (intValue * intNeg));
-  }
-
-DECODE_FRACTION:
-
-  if (ds->dec->preciseFloat)
-  {
-    return decodePreciseFloat(ds);
-  }
-
-  // Scan fraction part
-  frcValue = 0.0;
-  for (;;)
-  {
-    chr = (int) (unsigned char) *(offset);
-
-    switch (chr)
-    {
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-      {
-        if (decimalCount < JSON_DOUBLE_MAX_DECIMALS)
-        {
-          frcValue = frcValue * 10.0 + (double) (chr - 48);
-          decimalCount ++;
-        }
-        offset ++;
-        break;
-      }
-      case 'e':
-      case 'E':
-      {
-        offset ++;
-        goto DECODE_EXPONENT;
-        break;
-      }
-      default:
-      {
-        goto BREAK_FRC_LOOP;
-      }
-    }
-  }
-
-BREAK_FRC_LOOP:
-  //FIXME: Check for arithemtic overflow here
-  ds->lastType = JT_DOUBLE;
-  ds->start = offset;
-  return ds->dec->newDouble (ds->prv, createDouble( (double) intNeg, (double) intValue, frcValue, decimalCount));
-
-DECODE_EXPONENT:
-  if (ds->dec->preciseFloat)
-  {
-    return decodePreciseFloat(ds);
-  }
-
-  expNeg = 1.0;
-
-  if (*(offset) == '-')
-  {
-    expNeg = -1.0;
-    offset ++;
-  }
-  else
-  if (*(offset) == '+')
-  {
-    expNeg = +1.0;
-    offset ++;
-  }
-
-  expValue = 0.0;
-
-  for (;;)
-  {
-    chr = (int) (unsigned char) *(offset);
-
-    switch (chr)
-    {
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-      {
-        expValue = expValue * 10.0 + (double) (chr - 48);
-        offset ++;
-        break;
-      }
-      default:
-      {
-        goto BREAK_EXP_LOOP;
-      }
-    }
-  }
-
-BREAK_EXP_LOOP:
-  //FIXME: Check for arithemtic overflow here
-  ds->lastType = JT_DOUBLE;
-  ds->start = offset;
-  return ds->dec->newDouble (ds->prv, createDouble( (double) intNeg, (double) intValue , frcValue, decimalCount) * pow(10.0, expValue * expNeg));
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_true ( struct DecoderState *ds)
-{
-  char *offset = ds->start;
-  offset ++;
-
-  if (*(offset++) != 'r')
-    goto SETERROR;
-  if (*(offset++) != 'u')
-    goto SETERROR;
-  if (*(offset++) != 'e')
-    goto SETERROR;
-
-  ds->lastType = JT_TRUE;
-  ds->start = offset;
-  return ds->dec->newTrue(ds->prv);
-
-SETERROR:
-  return SetError(ds, -1, "Unexpected character found when decoding 'true'");
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_false ( struct DecoderState *ds)
-{
-  char *offset = ds->start;
-  offset ++;
-
-  if (*(offset++) != 'a')
-    goto SETERROR;
-  if (*(offset++) != 'l')
-    goto SETERROR;
-  if (*(offset++) != 's')
-    goto SETERROR;
-  if (*(offset++) != 'e')
-    goto SETERROR;
-
-  ds->lastType = JT_FALSE;
-  ds->start = offset;
-  return ds->dec->newFalse(ds->prv);
-
-SETERROR:
-  return SetError(ds, -1, "Unexpected character found when decoding 'false'");
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_null ( struct DecoderState *ds)
-{
-  char *offset = ds->start;
-  offset ++;
-
-  if (*(offset++) != 'u')
-    goto SETERROR;
-  if (*(offset++) != 'l')
-    goto SETERROR;
-  if (*(offset++) != 'l')
-    goto SETERROR;
-
-  ds->lastType = JT_NULL;
-  ds->start = offset;
-  return ds->dec->newNull(ds->prv);
-
-SETERROR:
-  return SetError(ds, -1, "Unexpected character found when decoding 'null'");
-}
-
-FASTCALL_ATTR void FASTCALL_MSVC SkipWhitespace(struct DecoderState *ds)
-{
-  char *offset = ds->start;
-
-  for (;;)
-  {
-    switch (*offset)
-    {
-      case ' ':
-      case '\t':
-      case '\r':
-      case '\n':
-        offset ++;
-        break;
-
-      default:
-        ds->start = offset;
-        return;
-    }
-  }
-}
-
-enum DECODESTRINGSTATE
-{
-  DS_ISNULL = 0x32,
-  DS_ISQUOTE,
-  DS_ISESCAPE,
-  DS_UTFLENERROR,
-
-};
-
-static const JSUINT8 g_decoderLookup[256] =
-{
-  /* 0x00 */ DS_ISNULL, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x20 */ 1, 1, DS_ISQUOTE, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, DS_ISESCAPE, 1, 1, 1,
-  /* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x80 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0x90 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0xa0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0xb0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-  /* 0xc0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  /* 0xd0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-  /* 0xe0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-  /* 0xf0 */ 4, 4, 4, 4, 4, 4, 4, 4, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR,
-};
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds)
-{
-  int index;
-  JSUINT32 *escOffset;
-  JSUINT32 *escStart;
-  size_t escLen = (ds->escEnd - ds->escStart);
-  JSUINT8 *inputOffset;
-  JSUTF16 ch = 0;
-  JSUINT8 *lastHighSurrogate = NULL;
-  JSUINT8 oct;
-  JSUTF32 ucs;
-  ds->lastType = JT_INVALID;
-  ds->start ++;
-
-  if ( (size_t) (ds->end - ds->start) > escLen)
-  {
-    size_t newSize = (ds->end - ds->start);
-
-    if (ds->escHeap)
-    {
-      if (newSize > (SIZE_MAX / sizeof(JSUINT32)))
-      {
-        return SetError(ds, -1, "Could not reserve memory block");
-      }
-      escStart = (JSUINT32 *)ds->dec->realloc(ds->escStart, newSize * sizeof(JSUINT32));
-      if (!escStart)
-      {
-        ds->dec->free(ds->escStart);
-        return SetError(ds, -1, "Could not reserve memory block");
-      }
-      ds->escStart = escStart;
-    }
-    else
-    {
-      JSUINT32 *oldStart = ds->escStart;
-      if (newSize > (SIZE_MAX / sizeof(JSUINT32)))
-      {
-        return SetError(ds, -1, "Could not reserve memory block");
-      }
-      ds->escStart = (JSUINT32 *) ds->dec->malloc(newSize * sizeof(JSUINT32));
-      if (!ds->escStart)
-      {
-        return SetError(ds, -1, "Could not reserve memory block");
-      }
-      ds->escHeap = 1;
-      memcpy(ds->escStart, oldStart, escLen * sizeof(JSUINT32));
-    }
-
-    ds->escEnd = ds->escStart + newSize;
-  }
-
-  escOffset = ds->escStart;
-  inputOffset = (JSUINT8 *) ds->start;
-
-  for (;;)
-  {
-    switch (g_decoderLookup[(JSUINT8)(*inputOffset)])
-    {
-      case DS_ISNULL:
-      {
-        return SetError(ds, -1, "Unmatched ''\"' when when decoding 'string'");
-      }
-      case DS_ISQUOTE:
-      {
-        ds->lastType = JT_UTF8;
-        inputOffset ++;
-        ds->start += ( (char *) inputOffset - (ds->start));
-        return ds->dec->newString(ds->prv, ds->escStart, escOffset);
-      }
-      case DS_UTFLENERROR:
-      {
-        return SetError (ds, -1, "Invalid UTF-8 sequence length when decoding 'string'");
-      }
-      case DS_ISESCAPE:
-        inputOffset ++;
-        switch (*inputOffset)
-        {
-          case '\\': *(escOffset++) = '\\'; inputOffset++; continue;
-          case '\"': *(escOffset++) = '\"'; inputOffset++; continue;
-          case '/':  *(escOffset++) = '/';  inputOffset++; continue;
-          case 'b':  *(escOffset++) = '\b'; inputOffset++; continue;
-          case 'f':  *(escOffset++) = '\f'; inputOffset++; continue;
-          case 'n':  *(escOffset++) = '\n'; inputOffset++; continue;
-          case 'r':  *(escOffset++) = '\r'; inputOffset++; continue;
-          case 't':  *(escOffset++) = '\t'; inputOffset++; continue;
-
-          case 'u':
-          {
-            int index;
-            inputOffset ++;
-
-            for (index = 0; index < 4; index ++)
-            {
-              switch (*inputOffset)
-              {
-                case '\0': return SetError (ds, -1, "Unterminated unicode escape sequence when decoding 'string'");
-                default: return SetError (ds, -1, "Unexpected character in unicode escape sequence when decoding 'string'");
-
-                case '0':
-                case '1':
-                case '2':
-                case '3':
-                case '4':
-                case '5':
-                case '6':
-                case '7':
-                case '8':
-                case '9':
-                  ch = (ch << 4) + (JSUTF16) (*inputOffset - '0');
-                  break;
-
-                case 'a':
-                case 'b':
-                case 'c':
-                case 'd':
-                case 'e':
-                case 'f':
-                  ch = (ch << 4) + 10 + (JSUTF16) (*inputOffset - 'a');
-                  break;
-
-                case 'A':
-                case 'B':
-                case 'C':
-                case 'D':
-                case 'E':
-                case 'F':
-                  ch = (ch << 4) + 10 + (JSUTF16) (*inputOffset - 'A');
-                  break;
-              }
-
-              inputOffset ++;
-            }
-
-            if ((ch & 0xfc00) == 0xdc00 && lastHighSurrogate == inputOffset - 6 * sizeof(*inputOffset))
-            {
-              // Low surrogate immediately following a high surrogate
-              // Overwrite existing high surrogate with combined character
-              *(escOffset-1) = (((*(escOffset-1) - 0xd800) <<10) | (ch - 0xdc00)) + 0x10000;
-            }
-            else
-            {
-              *(escOffset++) = (JSUINT32) ch;
-            }
-            if ((ch & 0xfc00) == 0xd800)
-            {
-              lastHighSurrogate = inputOffset;
-            }
-          break;
-        }
-
-        case '\0': return SetError(ds, -1, "Unterminated escape sequence when decoding 'string'");
-        default: return SetError(ds, -1, "Unrecognized escape sequence when decoding 'string'");
-      }
-      break;
-
-      case 1:
-      {
-        *(escOffset++) = (JSUINT32) (*inputOffset++);
-        break;
-      }
-
-      case 2:
-      {
-        ucs = (*inputOffset++) & 0x1f;
-        ucs <<= 6;
-        if (((*inputOffset) & 0x80) != 0x80)
-        {
-          return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'");
-        }
-        ucs |= (*inputOffset++) & 0x3f;
-        if (ucs < 0x80) return SetError (ds, -1, "Overlong 2 byte UTF-8 sequence detected when decoding 'string'");
-        *(escOffset++) = (JSUINT32) ucs;
-        break;
-      }
-
-      case 3:
-      {
-        JSUTF32 ucs = 0;
-        ucs |= (*inputOffset++) & 0x0f;
-
-        for (index = 0; index < 2; index ++)
-        {
-          ucs <<= 6;
-          oct = (*inputOffset++);
-
-          if ((oct & 0x80) != 0x80)
-          {
-            return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'");
-          }
-
-          ucs |= oct & 0x3f;
-        }
-
-        if (ucs < 0x800) return SetError (ds, -1, "Overlong 3 byte UTF-8 sequence detected when encoding string");
-        *(escOffset++) = (JSUINT32) ucs;
-        break;
-      }
-
-      case 4:
-      {
-        JSUTF32 ucs = 0;
-        ucs |= (*inputOffset++) & 0x07;
-
-        for (index = 0; index < 3; index ++)
-        {
-          ucs <<= 6;
-          oct = (*inputOffset++);
-
-          if ((oct & 0x80) != 0x80)
-          {
-            return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'");
-          }
-
-          ucs |= oct & 0x3f;
-        }
-
-        if (ucs < 0x10000) return SetError (ds, -1, "Overlong 4 byte UTF-8 sequence detected when decoding 'string'");
-
-        *(escOffset++) = (JSUINT32) ucs;
-        break;
-      }
-    }
-  }
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_array(struct DecoderState *ds)
-{
-  JSOBJ itemValue;
-  JSOBJ newObj;
-  int len;
-  ds->objDepth++;
-  if (ds->objDepth > JSON_MAX_OBJECT_DEPTH) {
-    return SetError(ds, -1, "Reached object decoding depth limit");
-  }
-
-  newObj = ds->dec->newArray(ds->prv);
-  len = 0;
-
-  ds->lastType = JT_INVALID;
-  ds->start ++;
-
-  for (;;)
-  {
-    SkipWhitespace(ds);
-
-    if ((*ds->start) == ']')
-    {
-      ds->objDepth--;
-      if (len == 0)
-      {
-        ds->start ++;
-        return newObj;
-      }
-
-      ds->dec->releaseObject(ds->prv, newObj);
-      return SetError(ds, -1, "Unexpected character found when decoding array value (1)");
-    }
-
-    itemValue = decode_any(ds);
-
-    if (itemValue == NULL)
-    {
-      ds->dec->releaseObject(ds->prv, newObj);
-      return NULL;
-    }
-
-    ds->dec->arrayAddItem (ds->prv, newObj, itemValue);
-
-    SkipWhitespace(ds);
-
-    switch (*(ds->start++))
-    {
-    case ']':
-    {
-      ds->objDepth--;
-      return newObj;
-    }
-    case ',':
-      break;
-
-    default:
-      ds->dec->releaseObject(ds->prv, newObj);
-      return SetError(ds, -1, "Unexpected character found when decoding array value (2)");
-    }
-
-    len ++;
-  }
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
-{
-  JSOBJ itemName;
-  JSOBJ itemValue;
-  JSOBJ newObj;
-  int len;
-
-  ds->objDepth++;
-  if (ds->objDepth > JSON_MAX_OBJECT_DEPTH) {
-    return SetError(ds, -1, "Reached object decoding depth limit");
-  }
-
-  newObj = ds->dec->newObject(ds->prv);
-  len = 0;
-
-  ds->start ++;
-
-  for (;;)
-  {
-    SkipWhitespace(ds);
-
-    if ((*ds->start) == '}')
-    {
-      ds->objDepth--;
-      if (len == 0)
-      {
-        ds->start ++;
-        return newObj;
-      }
-
-      ds->dec->releaseObject(ds->prv, newObj);
-      return SetError(ds, -1, "Unexpected character in found when decoding object value");
-    }
-
-    ds->lastType = JT_INVALID;
-    itemName = decode_any(ds);
-
-    if (itemName == NULL)
-    {
-      ds->dec->releaseObject(ds->prv, newObj);
-      return NULL;
-    }
-
-    if (ds->lastType != JT_UTF8)
-    {
-      ds->dec->releaseObject(ds->prv, newObj);
-      ds->dec->releaseObject(ds->prv, itemName);
-      return SetError(ds, -1, "Key name of object must be 'string' when decoding 'object'");
-    }
-
-    SkipWhitespace(ds);
-
-    if (*(ds->start++) != ':')
-    {
-      ds->dec->releaseObject(ds->prv, newObj);
-      ds->dec->releaseObject(ds->prv, itemName);
-      return SetError(ds, -1, "No ':' found when decoding object value");
-    }
-
-    SkipWhitespace(ds);
-
-    itemValue = decode_any(ds);
-
-    if (itemValue == NULL)
-    {
-      ds->dec->releaseObject(ds->prv, newObj);
-      ds->dec->releaseObject(ds->prv, itemName);
-      return NULL;
-    }
-
-    ds->dec->objectAddKey (ds->prv, newObj, itemName, itemValue);
-
-    SkipWhitespace(ds);
-
-    switch (*(ds->start++))
-    {
-      case '}':
-      {
-        ds->objDepth--;
-        return newObj;
-      }
-      case ',':
-        break;
-
-      default:
-        ds->dec->releaseObject(ds->prv, newObj);
-        return SetError(ds, -1, "Unexpected character in found when decoding object value");
-    }
-
-    len++;
-  }
-}
-
-FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_any(struct DecoderState *ds)
-{
-  for (;;)
-  {
-    switch (*ds->start)
-    {
-      case '\"':
-        return decode_string (ds);
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-      case '-':
-        return decode_numeric (ds);
-
-      case '[': return decode_array (ds);
-      case '{': return decode_object (ds);
-      case 't': return decode_true (ds);
-      case 'f': return decode_false (ds);
-      case 'n': return decode_null (ds);
-
-      case ' ':
-      case '\t':
-      case '\r':
-      case '\n':
-        // White space
-        ds->start ++;
-        break;
-
-      default:
-        return SetError(ds, -1, "Expected object or value");
-    }
-  }
-}
-
-JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuffer)
-{
-  /*
-  FIXME: Base the size of escBuffer of that of cbBuffer so that the unicode escaping doesn't run into the wall each time */
-  struct DecoderState ds;
-  JSUINT32 escBuffer[(JSON_MAX_STACK_BUFFER_SIZE / sizeof(JSUINT32))];
-  JSOBJ ret;
-
-  ds.start = (char *) buffer;
-  ds.end = ds.start + cbBuffer;
-
-  ds.escStart = escBuffer;
-  ds.escEnd = ds.escStart + (JSON_MAX_STACK_BUFFER_SIZE / sizeof(JSUINT32));
-  ds.escHeap = 0;
-  ds.prv = dec->prv;
-  ds.dec = dec;
-  ds.dec->errorStr = NULL;
-  ds.dec->errorOffset = NULL;
-  ds.objDepth = 0;
-
-  ds.dec = dec;
-
-  ret = decode_any (&ds);
-
-  if (ds.escHeap)
-  {
-    dec->free(ds.escStart);
-  }
-
-  if (!(dec->errorStr))
-  {
-    if ((ds.end - ds.start) > 0)
-    {
-      SkipWhitespace(&ds);
-    }
-
-    if (ds.start != ds.end && ret)
-    {
-      dec->releaseObject(ds.prv, ret);
-      return SetError(&ds, -1, "Trailing data");
-    }
-  }
-
-  return ret;
-}
diff --git a/srsly/ujson/lib/ultrajsonenc.c b/srsly/ujson/lib/ultrajsonenc.c
deleted file mode 100644
index ea6372b..0000000
--- a/srsly/ujson/lib/ultrajsonenc.c
+++ /dev/null
@@ -1,1067 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
- * Copyright (c) 1988-1993 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-#include "ultrajson.h"
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
-
-#include <float.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#if ( (defined(_WIN32) || defined(WIN32) ) && ( defined(_MSC_VER) ) )
-#define snprintf sprintf_s
-#endif
-
-/*
-Worst cases being:
-
-Control characters (ASCII < 32)
-0x00 (1 byte) input => \u0000 output (6 bytes)
-1 * 6 => 6 (6 bytes required)
-
-or UTF-16 surrogate pairs
-4 bytes input in UTF-8 => \uXXXX\uYYYY (12 bytes).
-
-4 * 6 => 24 bytes (12 bytes required)
-
-The extra 2 bytes are for the quotes around the string
-
-*/
-#define RESERVE_STRING(_len) (2 + ((_len) * 6))
-
-static const double g_pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000};
-static const char g_hexChars[] = "0123456789abcdef";
-static const char g_escapeChars[] = "0123456789\\b\\t\\n\\f\\r\\\"\\\\\\/";
-
-/*
-FIXME: While this is fine dandy and working it's a magic value mess which probably only the author understands.
-Needs a cleanup and more documentation */
-
-/*
-Table for pure ascii output escaping all characters above 127 to \uXXXX */
-static const JSUINT8 g_asciiOutputTable[256] =
-{
-/* 0x00 */ 0, 30, 30, 30, 30, 30, 30, 30, 10, 12, 14, 30, 16, 18, 30, 30,
-/* 0x10 */ 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-/* 0x20 */ 1, 1, 20, 1, 1, 1, 29, 1, 1, 1, 1, 1, 1, 1, 1, 24,
-/* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 1, 29, 1,
-/* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 1, 1, 1,
-/* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 0x80 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 0x90 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 0xa0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 0xb0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 0xc0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 0xd0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 0xe0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-/* 0xf0 */ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
-};
-
-static void SetError (JSOBJ obj, JSONObjectEncoder *enc, const char *message)
-{
-  enc->errorMsg = message;
-  enc->errorObj = obj;
-}
-
-/*
-FIXME: Keep track of how big these get across several encoder calls and try to make an estimate
-That way we won't run our head into the wall each call */
-void Buffer_Realloc (JSONObjectEncoder *enc, size_t cbNeeded)
-{
-  size_t free_space = enc->end - enc->offset;
-  if (free_space >= cbNeeded)
-  {
-    return;
-  }
-  size_t curSize = enc->end - enc->start;
-  size_t newSize = curSize;
-  size_t offset = enc->offset - enc->start;
-
-#ifdef DEBUG
-  // In debug mode, allocate only what is requested so that any miscalculation
-  // shows up plainly as a crash.
-  newSize = (enc->offset - enc->start) + cbNeeded;
-#else
-  while (newSize < curSize + cbNeeded)
-  {
-    newSize *= 2;
-  }
-#endif
-
-  if (enc->heap)
-  {
-    enc->start = (char *) enc->realloc (enc->start, newSize);
-    if (!enc->start)
-    {
-      SetError (NULL, enc, "Could not reserve memory block");
-      return;
-    }
-  }
-  else
-  {
-    char *oldStart = enc->start;
-    enc->heap = 1;
-    enc->start = (char *) enc->malloc (newSize);
-    if (!enc->start)
-    {
-      SetError (NULL, enc, "Could not reserve memory block");
-      return;
-    }
-    memcpy (enc->start, oldStart, offset);
-  }
-  enc->offset = enc->start + offset;
-  enc->end = enc->start + newSize;
-}
-
-#define Buffer_Reserve(__enc, __len) \
-    if ( (size_t) ((__enc)->end - (__enc)->offset) < (size_t) (__len))  \
-    {   \
-      Buffer_Realloc((__enc), (__len));\
-    }   \
-
-FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendShortHexUnchecked (char *outputOffset, unsigned short value)
-{
-  *(outputOffset++) = g_hexChars[(value & 0xf000) >> 12];
-  *(outputOffset++) = g_hexChars[(value & 0x0f00) >> 8];
-  *(outputOffset++) = g_hexChars[(value & 0x00f0) >> 4];
-  *(outputOffset++) = g_hexChars[(value & 0x000f) >> 0];
-}
-
-int Buffer_EscapeStringUnvalidated (JSONObjectEncoder *enc, const char *io, const char *end)
-{
-  char *of = (char *) enc->offset;
-
-  for (;;)
-  {
-    switch (*io)
-    {
-      case 0x00:
-      {
-        if (io < end)
-        {
-          *(of++) = '\\';
-          *(of++) = 'u';
-          *(of++) = '0';
-          *(of++) = '0';
-          *(of++) = '0';
-          *(of++) = '0';
-          break;
-        }
-        else
-        {
-          enc->offset += (of - enc->offset);
-          return TRUE;
-        }
-      }
-      case '\"': (*of++) = '\\'; (*of++) = '\"'; break;
-      case '\\': (*of++) = '\\'; (*of++) = '\\'; break;
-      case '\b': (*of++) = '\\'; (*of++) = 'b'; break;
-      case '\f': (*of++) = '\\'; (*of++) = 'f'; break;
-      case '\n': (*of++) = '\\'; (*of++) = 'n'; break;
-      case '\r': (*of++) = '\\'; (*of++) = 'r'; break;
-      case '\t': (*of++) = '\\'; (*of++) = 't'; break;
-
-      case '/':
-      {
-        if (enc->escapeForwardSlashes)
-        {
-          (*of++) = '\\';
-          (*of++) = '/';
-        }
-        else
-        {
-          // Same as default case below.
-          (*of++) = (*io);
-        }
-        break;
-      }
-      case 0x26: // '&'
-      case 0x3c: // '<'
-      case 0x3e: // '>'
-      {
-        if (enc->encodeHTMLChars)
-        {
-          // Fall through to \u00XX case below.
-        }
-        else
-        {
-          // Same as default case below.
-          (*of++) = (*io);
-          break;
-        }
-      }
-      case 0x01:
-      case 0x02:
-      case 0x03:
-      case 0x04:
-      case 0x05:
-      case 0x06:
-      case 0x07:
-      case 0x0b:
-      case 0x0e:
-      case 0x0f:
-      case 0x10:
-      case 0x11:
-      case 0x12:
-      case 0x13:
-      case 0x14:
-      case 0x15:
-      case 0x16:
-      case 0x17:
-      case 0x18:
-      case 0x19:
-      case 0x1a:
-      case 0x1b:
-      case 0x1c:
-      case 0x1d:
-      case 0x1e:
-      case 0x1f:
-      {
-        *(of++) = '\\';
-        *(of++) = 'u';
-        *(of++) = '0';
-        *(of++) = '0';
-        *(of++) = g_hexChars[ (unsigned char) (((*io) & 0xf0) >> 4)];
-        *(of++) = g_hexChars[ (unsigned char) ((*io) & 0x0f)];
-        break;
-      }
-      default: (*of++) = (*io); break;
-      }
-    io++;
-  }
-}
-
-int Buffer_EscapeStringValidated (JSOBJ obj, JSONObjectEncoder *enc, const char *io, const char *end)
-{
-  JSUTF32 ucs;
-  char *of = (char *) enc->offset;
-
-  for (;;)
-  {
-#ifdef DEBUG
-  // 6 is the maximum length of a single character (cf. RESERVE_STRING).
-  if ((io < end) && (enc->end - of < 6)) {
-    fprintf(stderr, "Ran out of buffer space during Buffer_EscapeStringValidated()\n");
-    abort();
-  }
-#endif
-    JSUINT8 utflen = g_asciiOutputTable[(unsigned char) *io];
-
-    switch (utflen)
-    {
-      case 0:
-      {
-        if (io < end)
-        {
-          *(of++) = '\\';
-          *(of++) = 'u';
-          *(of++) = '0';
-          *(of++) = '0';
-          *(of++) = '0';
-          *(of++) = '0';
-          io ++;
-          continue;
-        }
-        else
-        {
-          enc->offset += (of - enc->offset);
-          return TRUE;
-        }
-      }
-
-      case 1:
-      {
-        *(of++)= (*io++);
-        continue;
-      }
-
-      case 2:
-      {
-        JSUTF32 in;
-        JSUTF16 in16;
-
-        if (end - io < 1)
-        {
-          enc->offset += (of - enc->offset);
-          SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string");
-          return FALSE;
-        }
-
-        memcpy(&in16, io, sizeof(JSUTF16));
-        in = (JSUTF32) in16;
-
-#ifdef __LITTLE_ENDIAN__
-        ucs = ((in & 0x1f) << 6) | ((in >> 8) & 0x3f);
-#else
-        ucs = ((in & 0x1f00) >> 2) | (in & 0x3f);
-#endif
-
-        if (ucs < 0x80)
-        {
-          enc->offset += (of - enc->offset);
-          SetError (obj, enc, "Overlong 2 byte UTF-8 sequence detected when encoding string");
-          return FALSE;
-        }
-
-        io += 2;
-        break;
-      }
-
-      case 3:
-      {
-        JSUTF32 in;
-        JSUTF16 in16;
-        JSUINT8 in8;
-
-        if (end - io < 2)
-        {
-          enc->offset += (of - enc->offset);
-          SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string");
-          return FALSE;
-        }
-
-        memcpy(&in16, io, sizeof(JSUTF16));
-        memcpy(&in8, io + 2, sizeof(JSUINT8));
-#ifdef __LITTLE_ENDIAN__
-        in = (JSUTF32) in16;
-        in |= in8 << 16;
-        ucs = ((in & 0x0f) << 12) | ((in & 0x3f00) >> 2) | ((in & 0x3f0000) >> 16);
-#else
-        in = in16 << 8;
-        in |= in8;
-        ucs = ((in & 0x0f0000) >> 4) | ((in & 0x3f00) >> 2) | (in & 0x3f);
-#endif
-
-        if (ucs < 0x800)
-        {
-          enc->offset += (of - enc->offset);
-          SetError (obj, enc, "Overlong 3 byte UTF-8 sequence detected when encoding string");
-          return FALSE;
-        }
-
-        io += 3;
-        break;
-      }
-      case 4:
-      {
-        JSUTF32 in;
-
-        if (end - io < 3)
-        {
-          enc->offset += (of - enc->offset);
-          SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string");
-          return FALSE;
-        }
-
-        memcpy(&in, io, sizeof(JSUTF32));
-#ifdef __LITTLE_ENDIAN__
-        ucs = ((in & 0x07) << 18) | ((in & 0x3f00) << 4) | ((in & 0x3f0000) >> 10) | ((in & 0x3f000000) >> 24);
-#else
-        ucs = ((in & 0x07000000) >> 6) | ((in & 0x3f0000) >> 4) | ((in & 0x3f00) >> 2) | (in & 0x3f);
-#endif
-        if (ucs < 0x10000)
-        {
-          enc->offset += (of - enc->offset);
-          SetError (obj, enc, "Overlong 4 byte UTF-8 sequence detected when encoding string");
-          return FALSE;
-        }
-
-        io += 4;
-        break;
-      }
-
-
-      case 5:
-      case 6:
-      {
-        enc->offset += (of - enc->offset);
-        SetError (obj, enc, "Unsupported UTF-8 sequence length when encoding string");
-        return FALSE;
-      }
-
-      case 29:
-      {
-        if (enc->encodeHTMLChars)
-        {
-          // Fall through to \u00XX case 30 below.
-        }
-        else
-        {
-          // Same as case 1 above.
-          *(of++) = (*io++);
-          continue;
-        }
-      }
-
-      case 30:
-      {
-        // \uXXXX encode
-        *(of++) = '\\';
-        *(of++) = 'u';
-        *(of++) = '0';
-        *(of++) = '0';
-        *(of++) = g_hexChars[ (unsigned char) (((*io) & 0xf0) >> 4)];
-        *(of++) = g_hexChars[ (unsigned char) ((*io) & 0x0f)];
-        io ++;
-        continue;
-      }
-      case 10:
-      case 12:
-      case 14:
-      case 16:
-      case 18:
-      case 20:
-      case 22:
-      {
-        *(of++) = *( (char *) (g_escapeChars + utflen + 0));
-        *(of++) = *( (char *) (g_escapeChars + utflen + 1));
-        io ++;
-        continue;
-      }
-      case 24:
-      {
-        if (enc->escapeForwardSlashes)
-        {
-          *(of++) = *( (char *) (g_escapeChars + utflen + 0));
-          *(of++) = *( (char *) (g_escapeChars + utflen + 1));
-          io ++;
-        }
-        else
-        {
-          // Same as case 1 above.
-          *(of++) = (*io++);
-        }
-        continue;
-      }
-      // This can never happen, it's here to make L4 VC++ happy
-      default:
-      {
-        ucs = 0;
-        break;
-      }
-    }
-
-    /*
-    If the character is a UTF8 sequence of length > 1 we end up here */
-    if (ucs >= 0x10000)
-    {
-      ucs -= 0x10000;
-      *(of++) = '\\';
-      *(of++) = 'u';
-      Buffer_AppendShortHexUnchecked(of, (unsigned short) (ucs >> 10) + 0xd800);
-      of += 4;
-
-      *(of++) = '\\';
-      *(of++) = 'u';
-      Buffer_AppendShortHexUnchecked(of, (unsigned short) (ucs & 0x3ff) + 0xdc00);
-      of += 4;
-    }
-    else
-    {
-      *(of++) = '\\';
-      *(of++) = 'u';
-      Buffer_AppendShortHexUnchecked(of, (unsigned short) ucs);
-      of += 4;
-    }
-  }
-}
-
-static FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendCharUnchecked(JSONObjectEncoder *enc, char chr)
-{
-#ifdef DEBUG
-  if (enc->end <= enc->offset)
-  {
-    fprintf(stderr, "Overflow writing byte %d '%c'. The last few characters were:\n'''", chr, chr);
-    char * recent = enc->offset - 1000;
-    if (enc->start > recent)
-    {
-      recent = enc->start;
-    }
-    for (; recent < enc->offset; recent++)
-    {
-      fprintf(stderr, "%c", *recent);
-    }
-    fprintf(stderr, "'''\n");
-    abort();
-  }
-#endif
-  *(enc->offset++) = chr;
-}
-
-FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC strreverse(char* begin, char* end)
-{
-  char aux;
-  while (end > begin)
-  aux = *end, *end-- = *begin, *begin++ = aux;
-}
-
-void Buffer_AppendIndentNewlineUnchecked(JSONObjectEncoder *enc)
-{
-  if (enc->indent > 0) Buffer_AppendCharUnchecked(enc, '\n');
-}
-
-void Buffer_AppendIndentUnchecked(JSONObjectEncoder *enc, JSINT32 value)
-{
-  int i;
-  if (enc->indent > 0)
-    while (value-- > 0)
-      for (i = 0; i < enc->indent; i++)
-        Buffer_AppendCharUnchecked(enc, ' ');
-}
-
-void Buffer_AppendIntUnchecked(JSONObjectEncoder *enc, JSINT32 value)
-{
-  char* wstr;
-  JSUINT32 uvalue = (value < 0) ? -value : value;
-
-  wstr = enc->offset;
-  // Conversion. Number is reversed.
-
-  do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
-  if (value < 0) *wstr++ = '-';
-
-  // Reverse string
-  strreverse(enc->offset,wstr - 1);
-  enc->offset += (wstr - (enc->offset));
-}
-
-void Buffer_AppendLongUnchecked(JSONObjectEncoder *enc, JSINT64 value)
-{
-  char* wstr;
-  JSUINT64 uvalue = (value < 0) ? -value : value;
-
-  wstr = enc->offset;
-  // Conversion. Number is reversed.
-
-  do *wstr++ = (char)(48 + (uvalue % 10ULL)); while(uvalue /= 10ULL);
-  if (value < 0) *wstr++ = '-';
-
-  // Reverse string
-  strreverse(enc->offset,wstr - 1);
-  enc->offset += (wstr - (enc->offset));
-}
-
-void Buffer_AppendUnsignedLongUnchecked(JSONObjectEncoder *enc, JSUINT64 value)
-{
-  char* wstr;
-  JSUINT64 uvalue = value;
-
-  wstr = enc->offset;
-  // Conversion. Number is reversed.
-
-  do *wstr++ = (char)(48 + (uvalue % 10ULL)); while(uvalue /= 10ULL);
-
-  // Reverse string
-  strreverse(enc->offset,wstr - 1);
-  enc->offset += (wstr - (enc->offset));
-}
-
-int Buffer_AppendDoubleUnchecked(JSOBJ obj, JSONObjectEncoder *enc, double value)
-{
-  /* if input is larger than thres_max, revert to exponential */
-  const double thres_max = (double) 1e16 - 1;
-  int count;
-  double diff = 0.0;
-  char* str = enc->offset;
-  char* wstr = str;
-  unsigned long long whole;
-  double tmp;
-  unsigned long long frac;
-  int neg;
-  double pow10;
-
-  if (value == HUGE_VAL || value == -HUGE_VAL)
-  {
-    SetError (obj, enc, "Invalid Inf value when encoding double");
-    return FALSE;
-  }
-
-  if (!(value == value))
-  {
-    SetError (obj, enc, "Invalid Nan value when encoding double");
-    return FALSE;
-  }
-
-  /* we'll work in positive values and deal with the
-  negative sign issue later */
-  neg = 0;
-  if (value < 0)
-  {
-    neg = 1;
-    value = -value;
-  }
-
-  pow10 = g_pow10[enc->doublePrecision];
-
-  whole = (unsigned long long) value;
-  tmp = (value - whole) * pow10;
-  frac = (unsigned long long)(tmp);
-  diff = tmp - frac;
-
-  if (diff > 0.5)
-  {
-    ++frac;
-    /* handle rollover, e.g.  case 0.99 with prec 1 is 1.0  */
-    if (frac >= pow10)
-    {
-      frac = 0;
-      ++whole;
-    }
-  }
-  else
-  if (diff == 0.5 && ((frac == 0) || (frac & 1)))
-  {
-    /* if halfway, round up if odd, OR
-    if last digit is 0.  That last part is strange */
-    ++frac;
-  }
-
-  /* for very large numbers switch back to native sprintf for exponentials.
-  anyone want to write code to replace this? */
-  /*
-  normal printf behavior is to print EVERY whole number digit
-  which can be 100s of characters overflowing your buffers == bad
-  */
-  if (value > thres_max)
-  {
-     enc->offset += snprintf(str, enc->end - enc->offset, "%.15e", neg ? -value : value);
-     return TRUE;
-   }
-
-  if (enc->doublePrecision == 0)
-  {
-    diff = value - whole;
-
-    if (diff > 0.5)
-    {
-      /* greater than 0.5, round up, e.g. 1.6 -> 2 */
-      ++whole;
-    }
-    else
-    if (diff == 0.5 && (whole & 1))
-    {
-      /* exactly 0.5 and ODD, then round up */
-      /* 1.5 -> 2, but 2.5 -> 2 */
-      ++whole;
-    }
-
-  //vvvvvvvvvvvvvvvvvvv  Diff from modp_dto2
-  }
-    else
-    if (frac)
-    {
-      count = enc->doublePrecision;
-      // now do fractional part, as an unsigned number
-      // we know it is not 0 but we can have leading zeros, these
-      // should be removed
-      while (!(frac % 10))
-      {
-        --count;
-        frac /= 10;
-      }
-      //^^^^^^^^^^^^^^^^^^^  Diff from modp_dto2
-
-      // now do fractional part, as an unsigned number
-      do
-      {
-        --count;
-        *wstr++ = (char)(48 + (frac % 10));
-      } while (frac /= 10);
-      // add extra 0s
-      while (count-- > 0)
-      {
-        *wstr++ = '0';
-      }
-      // add decimal
-      *wstr++ = '.';
-    }
-    else
-    {
-      *wstr++ = '0';
-      *wstr++ = '.';
-    }
-
-    // do whole part
-    // Take care of sign
-    // Conversion. Number is reversed.
-    do *wstr++ = (char)(48 + (whole % 10)); while (whole /= 10);
-
-    if (neg)
-    {
-      *wstr++ = '-';
-    }
-    strreverse(str, wstr-1);
-    enc->offset += (wstr - (enc->offset));
-
-    return TRUE;
-}
-
-/*
-FIXME:
-Handle integration functions returning NULL here */
-
-/*
-FIXME:
-Perhaps implement recursion detection */
-
-void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
-{
-  const char *value;
-  char *objName;
-  int count;
-  JSOBJ iterObj;
-  size_t szlen;
-  JSONTypeContext tc;
-
-  if (enc->level > enc->recursionMax)
-  {
-    SetError (obj, enc, "Maximum recursion level reached");
-    return;
-  }
-
-  if (enc->errorMsg)
-  {
-    return;
-  }
-
-  if (name)
-  {
-    // 2 extra for the colon and optional space after it
-    Buffer_Reserve(enc, RESERVE_STRING(cbName) + 2);
-    Buffer_AppendCharUnchecked(enc, '\"');
-
-    if (enc->forceASCII)
-    {
-      if (!Buffer_EscapeStringValidated(obj, enc, name, name + cbName))
-      {
-        return;
-      }
-    }
-    else
-    {
-      if (!Buffer_EscapeStringUnvalidated(enc, name, name + cbName))
-      {
-        return;
-      }
-    }
-
-    Buffer_AppendCharUnchecked(enc, '\"');
-
-    Buffer_AppendCharUnchecked (enc, ':');
-    }
-
-    tc.encoder_prv = enc->prv;
-    enc->beginTypeContext(obj, &tc, enc);
-
-    /*
-    This reservation covers any additions on non-variable parts below, specifically:
-    - Opening brackets for JT_ARRAY and JT_OBJECT
-    - Number representation for JT_LONG, JT_ULONG, JT_INT, and JT_DOUBLE
-    - Constant value for JT_TRUE, JT_FALSE, JT_NULL
-    The length of 128 is the worst case length of the Buffer_AppendDoubleDconv addition.
-    The other types above all have smaller representations.
-    */
-    Buffer_Reserve (enc, 128);
-
-    switch (tc.type)
-    {
-      case JT_INVALID:
-      {
-        return;
-      }
-
-      case JT_ARRAY:
-      {
-        count = 0;
-
-        Buffer_AppendCharUnchecked (enc, '[');
-        Buffer_AppendIndentNewlineUnchecked (enc);
-
-        while (enc->iterNext(obj, &tc))
-        {
-          // The extra 2 bytes cover the comma and (optional) newline.
-          Buffer_Reserve (enc, enc->indent * (enc->level + 1) + 2);
-
-          if (count > 0)
-          {
-            Buffer_AppendCharUnchecked (enc, ',');
-            Buffer_AppendIndentNewlineUnchecked (enc);
-          }
-
-          iterObj = enc->iterGetValue(obj, &tc);
-
-          enc->level ++;
-          Buffer_AppendIndentUnchecked (enc, enc->level);
-          encode (iterObj, enc, NULL, 0);
-          count ++;
-      }
-
-      enc->iterEnd(obj, &tc);
-      // Reserve space for the indentation plus the newline.
-      Buffer_Reserve (enc, enc->indent * enc->level + 1);
-      Buffer_AppendIndentNewlineUnchecked (enc);
-      Buffer_AppendIndentUnchecked (enc, enc->level);
-      Buffer_Reserve (enc, 1);
-      Buffer_AppendCharUnchecked (enc, ']');
-      break;
-  }
-
-  case JT_OBJECT:
-  {
-    count = 0;
-
-    Buffer_AppendCharUnchecked (enc, '{');
-    Buffer_AppendIndentNewlineUnchecked (enc);
-
-    while (enc->iterNext(obj, &tc))
-    {
-      // The extra 2 bytes cover the comma and optional newline.
-      Buffer_Reserve (enc, enc->indent * (enc->level + 1) + 2);
-
-      if (count > 0)
-      {
-        Buffer_AppendCharUnchecked (enc, ',');
-        Buffer_AppendIndentNewlineUnchecked (enc);
-      }
-
-      iterObj = enc->iterGetValue(obj, &tc);
-      objName = enc->iterGetName(obj, &tc, &szlen);
-
-      enc->level ++;
-      Buffer_AppendIndentUnchecked (enc, enc->level);
-      encode (iterObj, enc, objName, szlen);
-      count ++;
-    }
-
-    enc->iterEnd(obj, &tc);
-    Buffer_Reserve (enc, enc->indent * enc->level + 1);
-    Buffer_AppendIndentNewlineUnchecked (enc);
-    Buffer_AppendIndentUnchecked (enc, enc->level);
-    Buffer_Reserve (enc, 1);
-    Buffer_AppendCharUnchecked (enc, '}');
-    break;
-  }
-
-  case JT_LONG:
-  {
-    Buffer_AppendLongUnchecked (enc, enc->getLongValue(obj, &tc));
-    break;
-  }
-
-  case JT_ULONG:
-  {
-    Buffer_AppendUnsignedLongUnchecked (enc, enc->getUnsignedLongValue(obj, &tc));
-    break;
-  }
-
-  case JT_INT:
-  {
-    Buffer_AppendIntUnchecked (enc, enc->getIntValue(obj, &tc));
-    break;
-  }
-
-  case JT_TRUE:
-  {
-    Buffer_AppendCharUnchecked (enc, 't');
-    Buffer_AppendCharUnchecked (enc, 'r');
-    Buffer_AppendCharUnchecked (enc, 'u');
-    Buffer_AppendCharUnchecked (enc, 'e');
-    break;
-  }
-
-  case JT_FALSE:
-  {
-    Buffer_AppendCharUnchecked (enc, 'f');
-    Buffer_AppendCharUnchecked (enc, 'a');
-    Buffer_AppendCharUnchecked (enc, 'l');
-    Buffer_AppendCharUnchecked (enc, 's');
-    Buffer_AppendCharUnchecked (enc, 'e');
-    break;
-  }
-
-
-  case JT_NULL:
-  {
-    Buffer_AppendCharUnchecked (enc, 'n');
-    Buffer_AppendCharUnchecked (enc, 'u');
-    Buffer_AppendCharUnchecked (enc, 'l');
-    Buffer_AppendCharUnchecked (enc, 'l');
-    break;
-  }
-
-  case JT_DOUBLE:
-  {
-    if (!Buffer_AppendDoubleUnchecked (obj, enc, enc->getDoubleValue(obj, &tc)))
-    {
-      enc->endTypeContext(obj, &tc);
-      enc->level --;
-      return;
-    }
-    break;
-  }
-
-  case JT_UTF8:
-  {
-      value = enc->getStringValue(obj, &tc, &szlen);
-      if(!value)
-      {
-        SetError(obj, enc, "utf-8 encoding error");
-        return;
-      }
-
-      Buffer_Reserve(enc, RESERVE_STRING(szlen));
-      if (enc->errorMsg)
-      {
-        enc->endTypeContext(obj, &tc);
-        return;
-      }
-      Buffer_AppendCharUnchecked (enc, '\"');
-
-      if (enc->forceASCII)
-      {
-        if (!Buffer_EscapeStringValidated(obj, enc, value, value + szlen))
-        {
-          enc->endTypeContext(obj, &tc);
-          enc->level --;
-          return;
-        }
-      }
-      else
-      {
-        if (!Buffer_EscapeStringUnvalidated(enc, value, value + szlen))
-        {
-          enc->endTypeContext(obj, &tc);
-          enc->level --;
-          return;
-        }
-      }
-
-      Buffer_AppendCharUnchecked (enc, '\"');
-      break;
-  }
-
-  case JT_RAW:
-  {
-      value = enc->getStringValue(obj, &tc, &szlen);
-      if(!value)
-      {
-        SetError(obj, enc, "utf-8 encoding error");
-        return;
-      }
-
-      Buffer_Reserve(enc, szlen);
-      if (enc->errorMsg)
-      {
-        enc->endTypeContext(obj, &tc);
-        return;
-      }
-
-      memcpy(enc->offset, value, szlen);
-      enc->offset += szlen;
-
-      break;
-    }
-  }
-
-  enc->endTypeContext(obj, &tc);
-  enc->level --;
-}
-
-char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *_buffer, size_t _cbBuffer)
-{
-  enc->malloc = enc->malloc ? enc->malloc : malloc;
-  enc->free =  enc->free ? enc->free : free;
-  enc->realloc = enc->realloc ? enc->realloc : realloc;
-  enc->errorMsg = NULL;
-  enc->errorObj = NULL;
-  enc->level = 0;
-
-  if (enc->recursionMax < 1)
-  {
-    enc->recursionMax = JSON_MAX_RECURSION_DEPTH;
-  }
-
-  if (enc->doublePrecision < 0 ||
-          enc->doublePrecision > JSON_DOUBLE_MAX_DECIMALS)
-  {
-    enc->doublePrecision = JSON_DOUBLE_MAX_DECIMALS;
-  }
-
-  if (_buffer == NULL)
-  {
-    _cbBuffer = 32768;
-    enc->start = (char *) enc->malloc (_cbBuffer);
-    if (!enc->start)
-    {
-      SetError(obj, enc, "Could not reserve memory block");
-      return NULL;
-    }
-    enc->heap = 1;
-  }
-  else
-  {
-    enc->start = _buffer;
-    enc->heap = 0;
-  }
-
-  enc->end = enc->start + _cbBuffer;
-  enc->offset = enc->start;
-
-  encode (obj, enc, NULL, 0);
-
-  Buffer_Reserve(enc, 1);
-  if (enc->errorMsg)
-  {
-    return NULL;
-  }
-  Buffer_AppendCharUnchecked(enc, '\0');
-
-  return enc->start;
-}
diff --git a/srsly/ujson/objToJSON.c b/srsly/ujson/objToJSON.c
deleted file mode 100644
index c22f861..0000000
--- a/srsly/ujson/objToJSON.c
+++ /dev/null
@@ -1,984 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
-* Copyright (c) 1988-1993 The Regents of the University of California.
-* Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-#include "py_defines.h"
-#include <stdio.h>
-#include <datetime.h>
-#include <ultrajson.h>
-
-#define EPOCH_ORD 719163
-static PyObject* type_decimal = NULL;
-
-typedef void *(*PFN_PyTypeToJSON)(JSOBJ obj, JSONTypeContext *ti, void *outValue, size_t *_outLen);
-
-#if (PY_VERSION_HEX < 0x02050000)
-typedef ssize_t Py_ssize_t;
-#endif
-
-typedef struct __TypeContext
-{
-  JSPFN_ITEREND iterEnd;
-  JSPFN_ITERNEXT iterNext;
-  JSPFN_ITERGETNAME iterGetName;
-  JSPFN_ITERGETVALUE iterGetValue;
-  PFN_PyTypeToJSON PyTypeToJSON;
-  PyObject *newObj;
-  PyObject *dictObj;
-  Py_ssize_t index;
-  Py_ssize_t size;
-  PyObject *itemValue;
-  PyObject *itemName;
-  PyObject *attrList;
-  PyObject *iterator;
-
-  union
-  {
-    PyObject *rawJSONValue;
-    JSINT64 longValue;
-    JSUINT64 unsignedLongValue;
-  };
-} TypeContext;
-
-#define GET_TC(__ptrtc) ((TypeContext *)((__ptrtc)->prv))
-
-struct PyDictIterState
-{
-  PyObject *keys;
-  size_t i;
-  size_t sz;
-};
-
-//#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__)
-#define PRINTMARK()
-
-void initObjToJSON(void)
-{
-  PyObject* mod_decimal = PyImport_ImportModule("decimal");
-  if (mod_decimal)
-  {
-    type_decimal = PyObject_GetAttrString(mod_decimal, "Decimal");
-    Py_INCREF(type_decimal);
-    Py_DECREF(mod_decimal);
-  }
-  else
-    PyErr_Clear();
-
-  PyDateTime_IMPORT;
-}
-
-#ifdef _LP64
-static void *PyIntToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = (PyObject *) _obj;
-  *((JSINT64 *) outValue) = PyInt_AS_LONG (obj);
-  return NULL;
-}
-#else
-static void *PyIntToINT32(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = (PyObject *) _obj;
-  *((JSINT32 *) outValue) = PyInt_AS_LONG (obj);
-  return NULL;
-}
-#endif
-
-static void *PyLongToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  *((JSINT64 *) outValue) = GET_TC(tc)->longValue;
-  return NULL;
-}
-
-static void *PyLongToUINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  *((JSUINT64 *) outValue) = GET_TC(tc)->unsignedLongValue;
-  return NULL;
-}
-
-static void *PyFloatToDOUBLE(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = (PyObject *) _obj;
-  *((double *) outValue) = PyFloat_AsDouble (obj);
-  return NULL;
-}
-
-static void *PyStringToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = (PyObject *) _obj;
-  *_outLen = PyString_GET_SIZE(obj);
-  return PyString_AS_STRING(obj);
-}
-
-static void *PyUnicodeToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = (PyObject *) _obj;
-  PyObject *newObj;
-#if (PY_VERSION_HEX >= 0x03030000)
-  if(PyUnicode_IS_COMPACT_ASCII(obj))
-  {
-    Py_ssize_t len;
-    char *data = PyUnicode_AsUTF8AndSize(obj, &len);
-    *_outLen = len;
-    return data;
-  }
-#endif
-  newObj = PyUnicode_AsUTF8String(obj);
-  if(!newObj)
-  {
-    return NULL;
-  }
-
-  GET_TC(tc)->newObj = newObj;
-
-  *_outLen = PyString_GET_SIZE(newObj);
-  return PyString_AS_STRING(newObj);
-}
-
-static void *PyRawJSONToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = GET_TC(tc)->rawJSONValue;
-  if (PyUnicode_Check(obj)) {
-    return PyUnicodeToUTF8(obj, tc, outValue, _outLen);
-  }
-  else {
-    return PyStringToUTF8(obj, tc, outValue, _outLen);
-  }
-}
-
-static void *PyDateTimeToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = (PyObject *) _obj;
-  PyObject *date, *ord, *utcoffset;
-  int y, m, d, h, mn, s, days;
-
-  utcoffset = PyObject_CallMethod(obj, "utcoffset", NULL);
-  if(utcoffset != Py_None){
-    obj = PyNumber_Subtract(obj, utcoffset);
-  }
-
-  y = PyDateTime_GET_YEAR(obj);
-  m = PyDateTime_GET_MONTH(obj);
-  d = PyDateTime_GET_DAY(obj);
-  h = PyDateTime_DATE_GET_HOUR(obj);
-  mn = PyDateTime_DATE_GET_MINUTE(obj);
-  s = PyDateTime_DATE_GET_SECOND(obj);
-
-  date = PyDate_FromDate(y, m, 1);
-  ord = PyObject_CallMethod(date, "toordinal", NULL);
-  days = PyInt_AS_LONG(ord) - EPOCH_ORD + d - 1;
-  Py_DECREF(date);
-  Py_DECREF(ord);
-  *( (JSINT64 *) outValue) = (((JSINT64) ((days * 24 + h) * 60 + mn)) * 60 + s);
-  return NULL;
-}
-
-static void *PyDateToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen)
-{
-  PyObject *obj = (PyObject *) _obj;
-  PyObject *date, *ord;
-  int y, m, d, days;
-
-  y = PyDateTime_GET_YEAR(obj);
-  m = PyDateTime_GET_MONTH(obj);
-  d = PyDateTime_GET_DAY(obj);
-
-  date = PyDate_FromDate(y, m, 1);
-  ord = PyObject_CallMethod(date, "toordinal", NULL);
-  days = PyInt_AS_LONG(ord) - EPOCH_ORD + d - 1;
-  Py_DECREF(date);
-  Py_DECREF(ord);
-  *( (JSINT64 *) outValue) = ((JSINT64) days * 86400);
-
-  return NULL;
-}
-
-int Tuple_iterNext(JSOBJ obj, JSONTypeContext *tc)
-{
-  PyObject *item;
-
-  if (GET_TC(tc)->index >= GET_TC(tc)->size)
-  {
-    return 0;
-  }
-
-  item = PyTuple_GET_ITEM (obj, GET_TC(tc)->index);
-
-  GET_TC(tc)->itemValue = item;
-  GET_TC(tc)->index ++;
-  return 1;
-}
-
-void Tuple_iterEnd(JSOBJ obj, JSONTypeContext *tc)
-{
-}
-
-JSOBJ Tuple_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  return GET_TC(tc)->itemValue;
-}
-
-char *Tuple_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
-{
-  return NULL;
-}
-
-int List_iterNext(JSOBJ obj, JSONTypeContext *tc)
-{
-  if (GET_TC(tc)->index >= GET_TC(tc)->size)
-  {
-    PRINTMARK();
-    return 0;
-  }
-
-  GET_TC(tc)->itemValue = PyList_GET_ITEM (obj, GET_TC(tc)->index);
-  GET_TC(tc)->index ++;
-  return 1;
-}
-
-void List_iterEnd(JSOBJ obj, JSONTypeContext *tc)
-{
-}
-
-JSOBJ List_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  return GET_TC(tc)->itemValue;
-}
-
-char *List_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
-{
-  return NULL;
-}
-
-//=============================================================================
-// Dict iteration functions
-// itemName might converted to string (Python_Str). Do refCounting
-// itemValue is borrowed from object (which is dict). No refCounting
-//=============================================================================
-
-int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc)
-{
-  PyObject* itemNameTmp;
-
-  if (GET_TC(tc)->itemName)
-  {
-    Py_DECREF(GET_TC(tc)->itemName);
-    GET_TC(tc)->itemName = NULL;
-  }
-
-  if (!(GET_TC(tc)->itemName = PyIter_Next(GET_TC(tc)->iterator)))
-  {
-    PRINTMARK();
-    return 0;
-  }
-
-  if (GET_TC(tc)->itemValue) {
-    Py_DECREF(GET_TC(tc)->itemValue);
-    GET_TC(tc)->itemValue = NULL;
-  }
-
-  if (!(GET_TC(tc)->itemValue = PyObject_GetItem(GET_TC(tc)->dictObj, GET_TC(tc)->itemName))) {
-    PRINTMARK();
-    return 0;
-  }
-
-  if (PyUnicode_Check(GET_TC(tc)->itemName))
-  {
-    itemNameTmp = GET_TC(tc)->itemName;
-    GET_TC(tc)->itemName = PyUnicode_AsUTF8String (itemNameTmp);
-    Py_DECREF(itemNameTmp);
-  }
-  else
-    if (!PyString_Check(GET_TC(tc)->itemName))
-    {
-      itemNameTmp = GET_TC(tc)->itemName;
-      GET_TC(tc)->itemName = PyObject_Str(itemNameTmp);
-      Py_DECREF(itemNameTmp);
-#if PY_MAJOR_VERSION >= 3
-      itemNameTmp = GET_TC(tc)->itemName;
-      GET_TC(tc)->itemName = PyUnicode_AsUTF8String (itemNameTmp);
-      Py_DECREF(itemNameTmp);
-#endif
-    }
-    PRINTMARK();
-    return 1;
-}
-
-void Dict_iterEnd(JSOBJ obj, JSONTypeContext *tc)
-{
-  if (GET_TC(tc)->itemName) {
-    Py_DECREF(GET_TC(tc)->itemName);
-    GET_TC(tc)->itemName = NULL;
-  }
-  if (GET_TC(tc)->itemValue) {
-    Py_DECREF(GET_TC(tc)->itemValue);
-    GET_TC(tc)->itemValue = NULL;
-  }
-  Py_CLEAR(GET_TC(tc)->iterator);
-  Py_DECREF(GET_TC(tc)->dictObj);
-  PRINTMARK();
-}
-
-JSOBJ Dict_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  return GET_TC(tc)->itemValue;
-}
-
-char *Dict_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
-{
-  *outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
-  return PyString_AS_STRING(GET_TC(tc)->itemName);
-}
-
-int SortedDict_iterNext(JSOBJ obj, JSONTypeContext *tc)
-{
-  PyObject *items = NULL, *item = NULL, *key = NULL, *value = NULL;
-  Py_ssize_t i, nitems;
-#if PY_MAJOR_VERSION >= 3
-  PyObject* keyTmp;
-#endif
-
-  // Upon first call, obtain a list of the keys and sort them. This follows the same logic as the
-  // stanard library's _json.c sort_keys handler.
-  if (GET_TC(tc)->newObj == NULL)
-  {
-    // Obtain the list of keys from the dictionary.
-    items = PyMapping_Keys(GET_TC(tc)->dictObj);
-    if (items == NULL)
-    {
-      goto error;
-    }
-    else if (!PyList_Check(items))
-    {
-      PyErr_SetString(PyExc_ValueError, "keys must return list");
-      goto error;
-    }
-
-    // Sort the list.
-    if (PyList_Sort(items) < 0)
-    {
-      goto error;
-    }
-
-    // Obtain the value for each key, and pack a list of (key, value) 2-tuples.
-    nitems = PyList_GET_SIZE(items);
-    for (i = 0; i < nitems; i++)
-    {
-      key = PyList_GET_ITEM(items, i);
-      value = PyDict_GetItem(GET_TC(tc)->dictObj, key);
-
-      // Subject the key to the same type restrictions and conversions as in Dict_iterGetValue.
-      if (PyUnicode_Check(key))
-      {
-        key = PyUnicode_AsUTF8String(key);
-      }
-      else if (!PyString_Check(key))
-      {
-        key = PyObject_Str(key);
-#if PY_MAJOR_VERSION >= 3
-        keyTmp = key;
-        key = PyUnicode_AsUTF8String(key);
-        Py_DECREF(keyTmp);
-#endif
-      }
-      else
-      {
-        Py_INCREF(key);
-      }
-
-      item = PyTuple_Pack(2, key, value);
-      if (item == NULL)
-      {
-        goto error;
-      }
-      if (PyList_SetItem(items, i, item))
-      {
-        goto error;
-      }
-      Py_DECREF(key);
-    }
-
-    // Store the sorted list of tuples in the newObj slot.
-    GET_TC(tc)->newObj = items;
-    GET_TC(tc)->size = nitems;
-  }
-
-  if (GET_TC(tc)->index >= GET_TC(tc)->size)
-  {
-    PRINTMARK();
-    return 0;
-  }
-
-  item = PyList_GET_ITEM(GET_TC(tc)->newObj, GET_TC(tc)->index);
-  GET_TC(tc)->itemName = PyTuple_GET_ITEM(item, 0);
-  GET_TC(tc)->itemValue = PyTuple_GET_ITEM(item, 1);
-  GET_TC(tc)->index++;
-  return 1;
-
-error:
-  Py_XDECREF(item);
-  Py_XDECREF(key);
-  Py_XDECREF(value);
-  Py_XDECREF(items);
-  return -1;
-}
-
-void SortedDict_iterEnd(JSOBJ obj, JSONTypeContext *tc)
-{
-  GET_TC(tc)->itemName = NULL;
-  GET_TC(tc)->itemValue = NULL;
-  Py_DECREF(GET_TC(tc)->newObj);
-  Py_DECREF(GET_TC(tc)->dictObj);
-  PRINTMARK();
-}
-
-JSOBJ SortedDict_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  return GET_TC(tc)->itemValue;
-}
-
-char *SortedDict_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
-{
-  *outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
-  return PyString_AS_STRING(GET_TC(tc)->itemName);
-}
-
-
-void SetupDictIter(PyObject *dictObj, TypeContext *pc, JSONObjectEncoder *enc)
-{
-  pc->dictObj = dictObj;
-  if (enc->sortKeys)
-  {
-    pc->iterEnd = SortedDict_iterEnd;
-    pc->iterNext = SortedDict_iterNext;
-    pc->iterGetValue = SortedDict_iterGetValue;
-    pc->iterGetName = SortedDict_iterGetName;
-    pc->index = 0;
-  }
-  else
-  {
-    pc->iterEnd = Dict_iterEnd;
-    pc->iterNext = Dict_iterNext;
-    pc->iterGetValue = Dict_iterGetValue;
-    pc->iterGetName = Dict_iterGetName;
-    pc->iterator = PyObject_GetIter(dictObj);
-  }
-}
-
-void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObjectEncoder *enc)
-{
-  PyObject *obj, *objRepr, *exc;
-  TypeContext *pc;
-  PRINTMARK();
-  if (!_obj)
-  {
-    tc->type = JT_INVALID;
-    return;
-  }
-
-  obj = (PyObject*) _obj;
-
-  tc->prv = PyObject_Malloc(sizeof(TypeContext));
-  pc = (TypeContext *) tc->prv;
-  if (!pc)
-  {
-    tc->type = JT_INVALID;
-    PyErr_NoMemory();
-    return;
-  }
-  pc->newObj = NULL;
-  pc->dictObj = NULL;
-  pc->itemValue = NULL;
-  pc->itemName = NULL;
-  pc->iterator = NULL;
-  pc->attrList = NULL;
-  pc->index = 0;
-  pc->size = 0;
-  pc->longValue = 0;
-  pc->rawJSONValue = NULL;
-
-  if (PyIter_Check(obj))
-  {
-    PRINTMARK();
-    goto ISITERABLE;
-  }
-
-  if (PyBool_Check(obj))
-  {
-    PRINTMARK();
-    tc->type = (obj == Py_True) ? JT_TRUE : JT_FALSE;
-    return;
-  }
-  else
-  if (PyLong_Check(obj))
-  {
-    PRINTMARK();
-    pc->PyTypeToJSON = PyLongToINT64;
-    tc->type = JT_LONG;
-    GET_TC(tc)->longValue = PyLong_AsLongLong(obj);
-
-    exc = PyErr_Occurred();
-    if (!exc)
-    {
-        return;
-    }
-
-    if (exc && PyErr_ExceptionMatches(PyExc_OverflowError))
-    {
-      PyErr_Clear();
-      pc->PyTypeToJSON = PyLongToUINT64;
-      tc->type = JT_ULONG;
-      GET_TC(tc)->unsignedLongValue = PyLong_AsUnsignedLongLong(obj);
-
-      exc = PyErr_Occurred();
-      if (exc && PyErr_ExceptionMatches(PyExc_OverflowError))
-      {
-        PRINTMARK();
-        goto INVALID;
-      }
-    }
-
-    return;
-  }
-  else
-  if (PyInt_Check(obj))
-  {
-    PRINTMARK();
-#ifdef _LP64
-    pc->PyTypeToJSON = PyIntToINT64; tc->type = JT_LONG;
-#else
-    pc->PyTypeToJSON = PyIntToINT32; tc->type = JT_INT;
-#endif
-    return;
-  }
-  else
-  if (PyString_Check(obj) && !PyObject_HasAttrString(obj, "__json__"))
-  {
-    PRINTMARK();
-    pc->PyTypeToJSON = PyStringToUTF8; tc->type = JT_UTF8;
-    return;
-  }
-  else
-  if (PyUnicode_Check(obj))
-  {
-    PRINTMARK();
-    pc->PyTypeToJSON = PyUnicodeToUTF8; tc->type = JT_UTF8;
-    return;
-  }
-  else
-  if (PyFloat_Check(obj) || (type_decimal && PyObject_IsInstance(obj, type_decimal)))
-  {
-    PRINTMARK();
-    pc->PyTypeToJSON = PyFloatToDOUBLE; tc->type = JT_DOUBLE;
-    return;
-  }
-  else
-  if (PyDateTime_Check(obj))
-  {
-    PRINTMARK();
-    pc->PyTypeToJSON = PyDateTimeToINT64; tc->type = JT_LONG;
-    return;
-  }
-  else
-  if (PyDate_Check(obj))
-  {
-    PRINTMARK();
-    pc->PyTypeToJSON = PyDateToINT64; tc->type = JT_LONG;
-    return;
-  }
-  else
-  if (obj == Py_None)
-  {
-    PRINTMARK();
-    tc->type = JT_NULL;
-    return;
-  }
-
-ISITERABLE:
-  if (PyDict_Check(obj))
-  {
-    PRINTMARK();
-    tc->type = JT_OBJECT;
-    SetupDictIter(obj, pc, enc);
-    Py_INCREF(obj);
-    return;
-  }
-  else
-  if (PyList_Check(obj))
-  {
-    PRINTMARK();
-    tc->type = JT_ARRAY;
-    pc->iterEnd = List_iterEnd;
-    pc->iterNext = List_iterNext;
-    pc->iterGetValue = List_iterGetValue;
-    pc->iterGetName = List_iterGetName;
-    GET_TC(tc)->index =  0;
-    GET_TC(tc)->size = PyList_GET_SIZE( (PyObject *) obj);
-    return;
-  }
-  else
-  if (PyTuple_Check(obj))
-  {
-    PRINTMARK();
-    tc->type = JT_ARRAY;
-    pc->iterEnd = Tuple_iterEnd;
-    pc->iterNext = Tuple_iterNext;
-    pc->iterGetValue = Tuple_iterGetValue;
-    pc->iterGetName = Tuple_iterGetName;
-    GET_TC(tc)->index = 0;
-    GET_TC(tc)->size = PyTuple_GET_SIZE( (PyObject *) obj);
-    GET_TC(tc)->itemValue = NULL;
-
-    return;
-  }
-
-  if (PyObject_HasAttrString(obj, "toDict"))
-  {
-    PyObject* toDictFunc = PyObject_GetAttrString(obj, "toDict");
-    PyObject* tuple = PyTuple_New(0);
-    PyObject* toDictResult = PyObject_Call(toDictFunc, tuple, NULL);
-    Py_DECREF(tuple);
-    Py_DECREF(toDictFunc);
-
-    if (toDictResult == NULL)
-    {
-      goto INVALID;
-    }
-
-    if (!PyDict_Check(toDictResult))
-    {
-      Py_DECREF(toDictResult);
-      tc->type = JT_NULL;
-      return;
-    }
-
-    PRINTMARK();
-    tc->type = JT_OBJECT;
-    SetupDictIter(toDictResult, pc, enc);
-    return;
-  }
-  else
-  if (PyObject_HasAttrString(obj, "__json__"))
-  {
-    PyObject* toJSONFunc = PyObject_GetAttrString(obj, "__json__");
-    PyObject* tuple = PyTuple_New(0);
-    PyObject* toJSONResult = PyObject_Call(toJSONFunc, tuple, NULL);
-    Py_DECREF(tuple);
-    Py_DECREF(toJSONFunc);
-
-    if (toJSONResult == NULL)
-    {
-      goto INVALID;
-    }
-
-    if (PyErr_Occurred())
-    {
-      Py_DECREF(toJSONResult);
-      goto INVALID;
-    }
-
-    if (!PyString_Check(toJSONResult) && !PyUnicode_Check(toJSONResult))
-    {
-      Py_DECREF(toJSONResult);
-      PyErr_Format (PyExc_TypeError, "expected string");
-      goto INVALID;
-    }
-
-    PRINTMARK();
-    pc->PyTypeToJSON = PyRawJSONToUTF8;
-    tc->type = JT_RAW;
-    GET_TC(tc)->rawJSONValue = toJSONResult;
-    return;
-  }
-
-  PRINTMARK();
-  PyErr_Clear();
-
-  objRepr = PyObject_Repr(obj);
-#if PY_MAJOR_VERSION >= 3
-  PyObject* str = PyUnicode_AsEncodedString(objRepr, "utf-8", "~E~");
-  PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyString_AS_STRING(str));
-  Py_XDECREF(str);
-#else
-  PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyString_AS_STRING(objRepr));
-#endif
-  Py_DECREF(objRepr);
-
-INVALID:
-  PRINTMARK();
-  tc->type = JT_INVALID;
-  PyObject_Free(tc->prv);
-  tc->prv = NULL;
-  return;
-}
-
-void Object_endTypeContext(JSOBJ obj, JSONTypeContext *tc)
-{
-  Py_XDECREF(GET_TC(tc)->newObj);
-
-  if (tc->type == JT_RAW)
-  {
-    Py_XDECREF(GET_TC(tc)->rawJSONValue);
-  }
-  PyObject_Free(tc->prv);
-  tc->prv = NULL;
-}
-
-const char *Object_getStringValue(JSOBJ obj, JSONTypeContext *tc, size_t *_outLen)
-{
-  return GET_TC(tc)->PyTypeToJSON (obj, tc, NULL, _outLen);
-}
-
-JSINT64 Object_getLongValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  JSINT64 ret;
-  GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL);
-  return ret;
-}
-
-JSUINT64 Object_getUnsignedLongValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  JSUINT64 ret;
-  GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL);
-  return ret;
-}
-
-JSINT32 Object_getIntValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  JSINT32 ret;
-  GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL);
-  return ret;
-}
-
-double Object_getDoubleValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  double ret;
-  GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL);
-  return ret;
-}
-
-static void Object_releaseObject(JSOBJ _obj)
-{
-  Py_DECREF( (PyObject *) _obj);
-}
-
-int Object_iterNext(JSOBJ obj, JSONTypeContext *tc)
-{
-  return GET_TC(tc)->iterNext(obj, tc);
-}
-
-void Object_iterEnd(JSOBJ obj, JSONTypeContext *tc)
-{
-  GET_TC(tc)->iterEnd(obj, tc);
-}
-
-JSOBJ Object_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
-{
-  return GET_TC(tc)->iterGetValue(obj, tc);
-}
-
-char *Object_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
-{
-  return GET_TC(tc)->iterGetName(obj, tc, outLen);
-}
-
-PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
-{
-  static char *kwlist[] = { "obj", "ensure_ascii", "double_precision", "encode_html_chars", "escape_forward_slashes", "sort_keys", "indent", NULL };
-
-  char buffer[65536];
-  char *ret;
-  PyObject *newobj;
-  PyObject *oinput = NULL;
-  PyObject *oensureAscii = NULL;
-  PyObject *oencodeHTMLChars = NULL;
-  PyObject *oescapeForwardSlashes = NULL;
-  PyObject *osortKeys = NULL;
-
-  JSONObjectEncoder encoder =
-  {
-    Object_beginTypeContext,
-    Object_endTypeContext,
-    Object_getStringValue,
-    Object_getLongValue,
-    Object_getUnsignedLongValue,
-    Object_getIntValue,
-    Object_getDoubleValue,
-    Object_iterNext,
-    Object_iterEnd,
-    Object_iterGetValue,
-    Object_iterGetName,
-    Object_releaseObject,
-    PyObject_Malloc,
-    PyObject_Realloc,
-    PyObject_Free,
-    -1, //recursionMax
-    10,  // default double precision setting
-    1, //forceAscii
-    0, //encodeHTMLChars
-    1, //escapeForwardSlashes
-    0, //sortKeys
-    0, //indent
-    NULL, //prv
-  };
-
-
-  PRINTMARK();
-
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OiOOOi", kwlist, &oinput, &oensureAscii, &encoder.doublePrecision, &oencodeHTMLChars, &oescapeForwardSlashes, &osortKeys, &encoder.indent))
-  {
-    return NULL;
-  }
-
-  if (oensureAscii != NULL && !PyObject_IsTrue(oensureAscii))
-  {
-    encoder.forceASCII = 0;
-  }
-
-  if (oencodeHTMLChars != NULL && PyObject_IsTrue(oencodeHTMLChars))
-  {
-    encoder.encodeHTMLChars = 1;
-  }
-
-  if (oescapeForwardSlashes != NULL && !PyObject_IsTrue(oescapeForwardSlashes))
-  {
-    encoder.escapeForwardSlashes = 0;
-  }
-
-  if (osortKeys != NULL && PyObject_IsTrue(osortKeys))
-  {
-    encoder.sortKeys = 1;
-  }
-
-  PRINTMARK();
-  ret = JSON_EncodeObject (oinput, &encoder, buffer, sizeof (buffer));
-  PRINTMARK();
-
-  if (PyErr_Occurred())
-  {
-    return NULL;
-  }
-
-  if (encoder.errorMsg)
-  {
-    if (ret != buffer)
-    {
-      encoder.free (ret);
-    }
-
-    PyErr_Format (PyExc_OverflowError, "%s", encoder.errorMsg);
-    return NULL;
-  }
-
-  newobj = PyString_FromString (ret);
-
-  if (ret != buffer)
-  {
-    encoder.free (ret);
-  }
-
-  PRINTMARK();
-
-  return newobj;
-}
-
-PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs)
-{
-  PyObject *data;
-  PyObject *file;
-  PyObject *string;
-  PyObject *write;
-  PyObject *argtuple;
-  PyObject *write_result;
-
-  PRINTMARK();
-
-  if (!PyArg_ParseTuple (args, "OO", &data, &file))
-  {
-    return NULL;
-  }
-
-  if (!PyObject_HasAttrString (file, "write"))
-  {
-    PyErr_Format (PyExc_TypeError, "expected file");
-    return NULL;
-  }
-
-  write = PyObject_GetAttrString (file, "write");
-
-  if (!PyCallable_Check (write))
-  {
-    Py_XDECREF(write);
-    PyErr_Format (PyExc_TypeError, "expected file");
-    return NULL;
-  }
-
-  argtuple = PyTuple_Pack(1, data);
-
-  string = objToJSON (self, argtuple, kwargs);
-
-  if (string == NULL)
-  {
-    Py_XDECREF(write);
-    Py_XDECREF(argtuple);
-    return NULL;
-  }
-
-  Py_XDECREF(argtuple);
-
-  argtuple = PyTuple_Pack (1, string);
-  if (argtuple == NULL)
-  {
-    Py_XDECREF(write);
-    return NULL;
-  }
-  write_result = PyObject_CallObject (write, argtuple);
-  if (write_result == NULL)
-  {
-    Py_XDECREF(write);
-    Py_XDECREF(argtuple);
-    return NULL;
-  }
-  
-  Py_DECREF(write_result);
-  Py_XDECREF(write);
-  Py_DECREF(argtuple);
-  Py_XDECREF(string);
-
-  PRINTMARK();
-
-  Py_RETURN_NONE;
-}
diff --git a/srsly/ujson/py_defines.h b/srsly/ujson/py_defines.h
deleted file mode 100644
index 2b38b41..0000000
--- a/srsly/ujson/py_defines.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
- * Copyright (c) 1988-1993 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-#include <Python.h>
-
-#if PY_MAJOR_VERSION >= 3
-
-#define PyInt_Check             PyLong_Check
-#define PyInt_AS_LONG           PyLong_AsLong
-#define PyInt_FromLong          PyLong_FromLong
-
-#define PyString_Check          PyBytes_Check
-#define PyString_GET_SIZE       PyBytes_GET_SIZE
-#define PyString_AS_STRING      PyBytes_AS_STRING
-
-#define PyString_FromString     PyUnicode_FromString
-
-#endif
diff --git a/srsly/ujson/ujson.c b/srsly/ujson/ujson.c
deleted file mode 100644
index d0b15c6..0000000
--- a/srsly/ujson/ujson.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
-* Copyright (c) 1988-1993 The Regents of the University of California.
-* Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-#include "py_defines.h"
-#include "version.h"
-
-/* objToJSON */
-PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs);
-void initObjToJSON(void);
-
-/* JSONToObj */
-PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs);
-
-/* objToJSONFile */
-PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs);
-
-/* JSONFileToObj */
-PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs);
-
-
-#define ENCODER_HELP_TEXT "Use ensure_ascii=false to output UTF-8. Pass in double_precision to alter the maximum digit precision of doubles. Set encode_html_chars=True to encode < > & as unicode escape sequences. Set escape_forward_slashes=False to prevent escaping / characters."
-
-static PyMethodDef ujsonMethods[] = {
-  {"encode", (PyCFunction) objToJSON, METH_VARARGS | METH_KEYWORDS, "Converts arbitrary object recursively into JSON. " ENCODER_HELP_TEXT},
-  {"decode", (PyCFunction) JSONToObj, METH_VARARGS | METH_KEYWORDS, "Converts JSON as string to dict object structure. Use precise_float=True to use high precision float decoder."},
-  {"dumps", (PyCFunction) objToJSON, METH_VARARGS | METH_KEYWORDS,  "Converts arbitrary object recursively into JSON. " ENCODER_HELP_TEXT},
-  {"loads", (PyCFunction) JSONToObj, METH_VARARGS | METH_KEYWORDS,  "Converts JSON as string to dict object structure. Use precise_float=True to use high precision float decoder."},
-  {"dump", (PyCFunction) objToJSONFile, METH_VARARGS | METH_KEYWORDS, "Converts arbitrary object recursively into JSON file. " ENCODER_HELP_TEXT},
-  {"load", (PyCFunction) JSONFileToObj, METH_VARARGS | METH_KEYWORDS, "Converts JSON as file to dict object structure. Use precise_float=True to use high precision float decoder."},
-  {NULL, NULL, 0, NULL}       /* Sentinel */
-};
-
-#if PY_MAJOR_VERSION >= 3
-
-static struct PyModuleDef moduledef = {
-  PyModuleDef_HEAD_INIT,
-  "ujson",
-  0,              /* m_doc */
-  -1,             /* m_size */
-  ujsonMethods,   /* m_methods */
-  NULL,           /* m_reload */
-  NULL,           /* m_traverse */
-  NULL,           /* m_clear */
-  NULL            /* m_free */
-};
-
-#define PYMODINITFUNC       PyObject *PyInit_ujson(void)
-#define PYMODULE_CREATE()   PyModule_Create(&moduledef)
-#define MODINITERROR        return NULL
-
-#else
-
-#define PYMODINITFUNC       PyMODINIT_FUNC initujson(void)
-#define PYMODULE_CREATE()   Py_InitModule("ujson", ujsonMethods)
-#define MODINITERROR        return
-
-#endif
-
-PYMODINITFUNC
-{
-  PyObject *module;
-  PyObject *version_string;
-
-  initObjToJSON();
-  module = PYMODULE_CREATE();
-
-  if (module == NULL)
-  {
-    MODINITERROR;
-  }
-
-  version_string = PyString_FromString (UJSON_VERSION);
-  PyModule_AddObject (module, "__version__", version_string);
-
-#if PY_MAJOR_VERSION >= 3
-  return module;
-#endif
-}
diff --git a/srsly/ujson/version.h b/srsly/ujson/version.h
deleted file mode 100644
index f0ce6bb..0000000
--- a/srsly/ujson/version.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-Developed by ESN, an Electronic Arts Inc. studio. 
-Copyright (c) 2014, Electronic Arts Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-* Neither the name of ESN, Electronic Arts Inc. nor the
-names of its contributors may be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE 
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
-http://code.google.com/p/stringencoders/
-Copyright (c) 2007  Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
-
-Numeric decoder derived from from TCL library
-http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
- * Copyright (c) 1988-1993 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
-*/
-
-#define UJSON_VERSION "1.35"
