Files
pulse-sdk-py/src/adv_types.py
T
2026-07-28 06:49:43 +02:00

86 lines
1.7 KiB
Python

import struct
from decimal import Decimal
def pwp_number(fmt, value_type):
size = struct.calcsize(fmt)
def decorator(cls):
def __init__(self, value):
self.value = value_type(value)
def to_com(self):
return struct.pack(fmt, self.value)
@classmethod
def from_com(cls, data, offset=0):
value = struct.unpack_from(fmt, data, offset)[0]
return cls(value), offset + size
cls.__init__ = __init__
cls.to_com = to_com
cls.from_com = from_com
return cls
return decorator
# Unsigned integers
@pwp_number("<B", int)
class u8: pass
@pwp_number("<H", int)
class u16: pass
@pwp_number("<I", int)
class u32: pass
@pwp_number("<Q", int)
class u64: pass
# Signed integers
@pwp_number("<b", int)
class i8: pass
@pwp_number("<h", int)
class i16: pass
@pwp_number("<i", int)
class i32: pass
@pwp_number("<q", int)
class i64: pass
# Floating point
@pwp_number("<f", float)
class f32: pass
@pwp_number("<d", float)
class f64: pass
class decimal:
size = struct.calcsize("<qb")
def __init__(self, value):
self.value = Decimal(value)
def to_com(self):
sign, digits, exponent = self.value.as_tuple()
if not isinstance(exponent, int):
raise ValueError("Cannot serialize NaN or Infinity")
scale = -exponent
integer = int("".join(map(str, digits)))
if sign:
integer = -integer
return struct.pack("<qb", integer, scale)
@classmethod
def from_com(cls, data, offset=0):
integer, scale = struct.unpack_from("<qb", data, offset)
value = Decimal(integer) / (Decimal(10) ** scale)
return cls(value), offset + cls.size