diff --git a/CHANGELOG.md b/CHANGELOG.md index d78e50d8ebdf89c71512502b8f602d827a0e8875..909a9d8c9518595f465ede7446a6d768146a26e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,5 +4,6 @@ here's only the changelog for the version in development # v2.0 * fixed a bug with serializing uint32a +* added support for arbitrarily large integers * major refactor * backwards compatible 100% diff --git a/docs/specification.rst b/docs/specification.rst index 5fc538db0da4161e0362c8d9c0856e882501ce1c..bde7dc73e0d3cba025630da628e3026c84f4fbd5 100644 --- a/docs/specification.rst +++ b/docs/specification.rst @@ -63,3 +63,5 @@ Type Value consists of: and then follow that many pairs of Values (key: value) * If value is 22, then it's True * If value is 23, then it's False +* If value is 24, then next what comes is count of bytes, and then bytes follow. This is to be + interpreted as a signed integer diff --git a/minijson.pyx b/minijson.pyx index 378752ecf200f9bf6e9640d677227a3c3768ad71..6dc239e46432ded169057fb1bc066f34b83f6887 100644 --- a/minijson.pyx +++ b/minijson.pyx @@ -274,6 +274,10 @@ cpdef tuple parse(bytes data, int starting_position): return 1, True elif value_type == 23: return 1, False + elif value_type == 24: + length = data[starting_position+1] + byte_data = data[starting_position+2:starting_position+2+length] + return length+2, int.from_bytes(byte_data, 'big', signed=True) else: raise DecodingError('Unknown sequence type %s!' % (value_type, )) except (IndexError, struct.error) as e: @@ -302,6 +306,7 @@ cpdef int dump(object data, cio: io.BytesIO) except -1: cdef: str field_name int length + bytes b_data if data is None: cio.write(b'\x08') return 1 @@ -364,7 +369,15 @@ cpdef int dump(object data, cio: io.BytesIO) except -1: cio.write(STRUCT_L.pack(data)) return 5 else: - raise EncodingError('Too large integer %s' % (data, )) + length = 5 + while True: + try: + b_data = data.to_bytes(length, 'big', signed=True) + break + except OverflowError: + length += 1 + cio.write(bytearray([0x18, length])) + cio.write(b_data) elif isinstance(data, float): if float_encoding_mode == 0: cio.write(b'\x09') diff --git a/setup.cfg b/setup.cfg index 5fd7992f4c290a0cd504b285a199ba14e07025c9..6594f71adcf8f0818cb4c79dd2efcca9f6893da4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,6 @@ # coding: utf-8 [metadata] +version = 2.0 name = minijson long-description = file: README.md long-description-content-type = text/markdown; charset=UTF-8 diff --git a/setup.py b/setup.py index 483866977b8af3bd199ef42152708a4ad8ec5f50..71dc8e980a8c0f3fb1c179195451be6a80cfc98c 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,8 @@ import os -from distutils.extension import Extension from Cython.Build import cythonize from Cython.Compiler.Options import get_directive_defaults -from distutils.core import setup +from setuptools import setup, Extension directive_defaults = get_directive_defaults() directive_defaults['language_level'] = '3' @@ -15,10 +14,6 @@ if 'DEBUG' in os.environ: directive_defaults['binding'] = True macros = [('CYTHON_TRACE', '1')] -extensions = [Extension("minijson", ["minijson.pyx"], - define_macros=macros), - ] -setup(version='2.0', - ext_modules=cythonize(extensions), - ) +setup(ext_modules=cythonize([Extension("minijson", ["minijson.pyx"], + define_macros=macros)])) diff --git a/tests/test_minijson.py b/tests/test_minijson.py index e50c4a662e803b157d02898f68bbcb74f49d6580..0a312c3466ef98719b7f09005f7066911061203a 100644 --- a/tests/test_minijson.py +++ b/tests/test_minijson.py @@ -97,12 +97,10 @@ class TestMiniJSON(unittest.TestCase): self.assertSameAfterDumpsAndLoads(-0x7FFF) self.assertSameAfterDumpsAndLoads(-0xFFFF) self.assertSameAfterDumpsAndLoads(0x1FFFF) - b = dumps(0xFFFFFFFF) - print('Serialized to %s' % (b, )) - c = loads(b) - self.assertEqual(0xFFFFFFFF, c) + self.assertSameAfterDumpsAndLoads(0xFFFFFFFF) self.assertSameAfterDumpsAndLoads(0x1FFFFFF) - self.assertRaises(EncodingError, lambda: dumps(0xFFFFFFFFF)) + self.assertSameAfterDumpsAndLoads(0xFFFFFFFFF) + self.assertSameAfterDumpsAndLoads(0xFFFFFFFFFFFFF) def test_dumps(self): v = {"name": "land", "operator_id": "dupa", "parameters":