thelennylord / brigadier.py

Implementation of Mojang's brigadier in Python
https://pypi.org/project/brigadier.py
MIT License
4 stars 1 forks source link

string_reader verify numeric types #1

Open NickNackGus opened 3 years ago

NickNackGus commented 3 years ago

I see you've ported a good deal of brigadier to Python. It looks like in version 1.1 the string reader's long and double reading code is commented out, though. I'm willing to help if you can tell me what needs to be done.

From what I understand, Python integers aren't limited to 32 bits or 64 bits, and can be as large as you have the memory to store. Python floats are almost always 64 bit double-precision floating point numbers, but could be something else on some systems. This means that the code you have for int and float should be able to handle long and double, but you may need to either do some checks to ensure the values can be represented properly, or to convert to bytes and back and ensure the value is the same using something like struct.pack(">f", float(number)).

thelennylord commented 3 years ago

Initially, I've planned not to implement double and long into the string reader due to the behaviour of integers and floats in Python. However later I decided to implement them for compatibility purposes but haven't gotten around on how to handle them properly in Python.

Currently what needs to be done is able to differentiate Python integers and floats into 32-bit and 64-bit and decide whether they're long or double and handling them accordingly.

NickNackGus commented 3 years ago

I've looked around the code for a bit, and I think I can see why you'd want separate types for int/long and float/double at least in those places. I'm not sure it significantly matters in Python, but if you want to commit to it, I'd consider NumPy.

Your setup.py would need:

         "Topic :: Software Development :: Libraries :: Python Modules"
     ],
+    install_requires=[
+        "numpy"
+    ],
     python_requires=">=3.7"

Which adds the types:

numpy.int32
numpy.int64
numpy.float32
numpy.float64

# Examples for casting to these:
i = numpy.int32("0")
print(repr(i))
# 0
print(type(i))
# <class 'numpy.int32'>
i = numpy.int32(2**31)
print(i)
# -2147483648
print(type(i))
# <class 'numpy.int32'>
i -= 1
print(i)
# -2147483649
print(type(i))
# <class 'numpy.int64'>
i = numpy.int32(i)
print(i)
# 2147483647

Not a perfect solution because it changes type to avoid leaving the expected numeric limits, but good enough to request a specific type and check you got it back.

thelennylord commented 3 years ago

NumPy doesn't seem to work on Windows 10 2004 due to a bug for some time now. I'll hold off using NumPy until the bug has been resolved.

From your initial solution of using struct, we could try packing floats in the read_float method and check if it throws an overflow error, which would mean that the given float is a double. Similar logic could be implemented for the read_int method. What do you think about it?