Palworld-co-op-to-server-fix/lib/noindent.py

66 lines
2.3 KiB
Python

import ctypes
import json
import re
import uuid
class NoIndent(object):
"""Value wrapper."""
def __init__(self, value):
if not isinstance(value, (list, tuple)):
raise TypeError("Only lists and tuples can be wrapped")
self.value = value
class CustomEncoder(json.JSONEncoder):
FORMAT_SPEC = "@@{}@@"
regex = re.compile(FORMAT_SPEC.format(r"(\d+)"))
def __init__(self, **kwargs):
# Keyword arguments to ignore when encoding NoIndent wrapped values.
ignore = {"cls", "indent"}
# Save copy of any keyword argument values needed for use here.
self._kwargs = {k: v for k, v in kwargs.items() if k not in ignore}
super(CustomEncoder, self).__init__(**kwargs)
def default(self, obj):
if isinstance(obj, NoIndent):
return self.FORMAT_SPEC.format(id(obj))
elif isinstance(obj, uuid.UUID):
return str(obj)
return super(CustomEncoder, self).default(obj)
def iterencode(self, obj, **kwargs):
format_spec = self.FORMAT_SPEC # Local var to expedite access.
# Replace any marked-up NoIndent wrapped values in the JSON repr
# with the json.dumps() of the corresponding wrapped Python object.
for encoded in super(CustomEncoder, self).iterencode(obj, **kwargs):
match = self.regex.search(encoded)
if match:
id = int(match.group(1))
no_indent = ctypes.cast(id, ctypes.py_object).value
json_repr = json.dumps(no_indent.value, **self._kwargs)
# Replace the matched id string with json formatted representation
# of the corresponding Python object.
encoded = encoded.replace(
'"{}"'.format(format_spec.format(id)), json_repr
)
yield encoded
class NoIndentByteDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, dct):
if "value" in dct:
if "values" in dct["value"]:
if isinstance(dct["value"]["values"], list):
if isinstance(dct["value"]["values"][0], int):
dct["value"]["values"] = NoIndent(dct["value"]["values"])
return dct