You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
3.9 KiB
164 lines
3.9 KiB
from trezor.utils import obj_eq, obj_repr
|
|
|
|
from apps.monero.xmr.serialize.base_types import XmrType
|
|
from apps.monero.xmr.serialize.int_serialize import (
|
|
dump_uint,
|
|
dump_uvarint,
|
|
load_uint,
|
|
load_uvarint,
|
|
)
|
|
|
|
|
|
class UnicodeType(XmrType):
|
|
"""
|
|
Unicode data in UTF-8 encoding.
|
|
"""
|
|
|
|
@staticmethod
|
|
def dump(writer, s):
|
|
dump_uvarint(writer, len(s))
|
|
writer.write(bytes(s))
|
|
|
|
@staticmethod
|
|
def load(reader):
|
|
ivalue = load_uvarint(reader)
|
|
fvalue = bytearray(ivalue)
|
|
reader.readinto(fvalue)
|
|
return str(fvalue)
|
|
|
|
|
|
class BlobType(XmrType):
|
|
"""
|
|
Binary data, represented as bytearray. BlobType is only a scheme
|
|
descriptor. Behaves in the same way as primitive types.
|
|
"""
|
|
|
|
FIX_SIZE = 0
|
|
SIZE = 0
|
|
|
|
@classmethod
|
|
def dump(cls, writer, elem: bytes):
|
|
if cls.FIX_SIZE:
|
|
if cls.SIZE != len(elem):
|
|
raise ValueError("Size mismatch")
|
|
else:
|
|
dump_uvarint(writer, len(elem))
|
|
writer.write(elem)
|
|
|
|
@classmethod
|
|
def load(cls, reader) -> bytearray:
|
|
if cls.FIX_SIZE:
|
|
size = cls.SIZE
|
|
else:
|
|
size = load_uvarint(reader)
|
|
elem = bytearray(size)
|
|
reader.readinto(elem)
|
|
return elem
|
|
|
|
|
|
class ContainerType(XmrType):
|
|
"""
|
|
Array of elements, represented as a list of items. ContainerType is only a
|
|
scheme descriptor.
|
|
"""
|
|
|
|
FIX_SIZE = 0
|
|
SIZE = 0
|
|
ELEM_TYPE = None
|
|
|
|
@classmethod
|
|
def dump(cls, writer, elems, elem_type=None):
|
|
if elem_type is None:
|
|
elem_type = cls.ELEM_TYPE
|
|
if cls.FIX_SIZE:
|
|
if cls.SIZE != len(elems):
|
|
raise ValueError("Size mismatch")
|
|
else:
|
|
dump_uvarint(writer, len(elems))
|
|
for elem in elems:
|
|
elem_type.dump(writer, elem)
|
|
|
|
@classmethod
|
|
def load(cls, reader, elem_type=None):
|
|
if elem_type is None:
|
|
elem_type = cls.ELEM_TYPE
|
|
if cls.FIX_SIZE:
|
|
size = cls.SIZE
|
|
else:
|
|
size = load_uvarint(reader)
|
|
elems = []
|
|
for _ in range(size):
|
|
elem = elem_type.load(reader)
|
|
elems.append(elem)
|
|
return elems
|
|
|
|
|
|
class VariantType(XmrType):
|
|
"""
|
|
Union of types, differentiated by variant tags. VariantType is only a scheme
|
|
descriptor.
|
|
"""
|
|
|
|
@classmethod
|
|
def dump(cls, writer, elem):
|
|
for field in cls.f_specs():
|
|
ftype = field[1]
|
|
if isinstance(elem, ftype):
|
|
break
|
|
else:
|
|
raise ValueError("Unrecognized variant: %s" % elem)
|
|
|
|
dump_uint(writer, ftype.VARIANT_CODE, 1)
|
|
ftype.dump(writer, elem)
|
|
|
|
@classmethod
|
|
def load(cls, reader):
|
|
tag = load_uint(reader, 1)
|
|
for field in cls.f_specs():
|
|
ftype = field[1]
|
|
if ftype.VARIANT_CODE == tag:
|
|
fvalue = ftype.load(reader)
|
|
break
|
|
else:
|
|
raise ValueError("Unknown tag: %s" % tag)
|
|
return fvalue
|
|
|
|
@classmethod
|
|
def f_specs(cls):
|
|
return ()
|
|
|
|
|
|
class MessageType(XmrType):
|
|
"""
|
|
Message composed of fields with specific types.
|
|
"""
|
|
|
|
def __init__(self, **kwargs):
|
|
for kw in kwargs:
|
|
setattr(self, kw, kwargs[kw])
|
|
|
|
__eq__ = obj_eq
|
|
__repr__ = obj_repr
|
|
|
|
@classmethod
|
|
def dump(cls, writer, msg):
|
|
defs = cls.f_specs()
|
|
for field in defs:
|
|
fname, ftype, *fparams = field
|
|
fvalue = getattr(msg, fname, None)
|
|
ftype.dump(writer, fvalue, *fparams)
|
|
|
|
@classmethod
|
|
def load(cls, reader):
|
|
msg = cls()
|
|
defs = cls.f_specs()
|
|
for field in defs:
|
|
fname, ftype, *fparams = field
|
|
fvalue = ftype.load(reader, *fparams)
|
|
setattr(msg, fname, fvalue)
|
|
return msg
|
|
|
|
@classmethod
|
|
def f_specs(cls):
|
|
return ()
|