Implement write for Decimal (basic implementation)

This commit is contained in:
RunasSudo 2025-04-21 21:46:22 +10:00
parent d6177bec53
commit 4b76aeabb9
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
2 changed files with 24 additions and 2 deletions

View File

@ -14,10 +14,12 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from decimal import Decimal
import io
import struct
from typing import List
from .decimal import decimal_to_int32
from .known_types import CslaKnownTypes
from .serialization_info import SerializationInfo
@ -95,12 +97,15 @@ class CslaBinaryWriter:
if isinstance(value, bool):
return self.write_object_bool(value)
if isinstance(value, bytes):
return self.write_object_bytearray(value)
if isinstance(value, Decimal):
return self.write_object_decimal(value)
if isinstance(value, str):
return self.write_object_string(value)
if isinstance(value, bytes):
return self.write_object_bytearray(value)
raise NotImplementedError('CslaBinaryWriter.Write not implemented for type {}'.format(type(value).__name__))
def write_object_bool(self, value):
@ -113,6 +118,14 @@ class CslaBinaryWriter:
self.write_int32(len(value))
self.stream.write(value)
def write_object_decimal(self, value):
# CslaBinaryWriter.Write(Decimal)
self.stream.write(bytes([CslaKnownTypes.Decimal.value]))
int32_repr = decimal_to_int32(value)
self.write_int32(len(int32_repr)) # Should be 4 always
for part in int32_repr:
self.write_int32(part)
def write_object_int32(self, value):
# CslaBinaryWriter.Write(int)
self.stream.write(bytes([CslaKnownTypes.Int32.value]))

View File

@ -47,6 +47,15 @@ def int32_to_decimal(decimal_parts: List[int]) -> Decimal:
return Decimal(mantissa * (-1 if sign == 1 else 1)) / (Decimal(10) ** exponent)
def decimal_to_int32(decimal: Decimal) -> List[int]:
# FIXME: Only supports 32-bit integers
if decimal != decimal.to_integral_value():
raise NotImplementedError('decimal_to_int32 only supports 32-bit integers')
if decimal < Decimal('0') or decimal >= Decimal('2') ** 32:
raise NotImplementedError('decimal_to_int32 only supports 32-bit integers')
return [int(decimal), 0, 0, 0]
def test_int32_to_decimal():
# https://learn.microsoft.com/en-us/dotnet/api/system.decimal.-ctor?view=net-9.0#system-decimal-ctor(system-int32())
assert int32_to_decimal([0x0, 0x0, 0x0, 0x0]) == Decimal('0')