import struct
import p2pool
+from p2pool.util import memoize
class EarlyEnd(Exception):
pass
raise AssertionError((self._unpack(data), obj))
return data
+
+ def packed_size(self, obj):
+ if hasattr(obj, '_packed_size') and obj._packed_size is not None:
+ type_obj, packed_size = obj._packed_size
+ if type_obj is self:
+ return packed_size
+
+ packed_size = len(self.pack(obj))
+
+ if hasattr(obj, '_packed_size'):
+ obj._packed_size = self, packed_size
+
+ return packed_size
class VarIntType(Type):
def read(self, file):
def read(self, file):
length, file = self._inner_size.read(file)
- res = []
+ res = [None]*length
for i in xrange(length):
- item, file = self.type.read(file)
- res.append(item)
+ res[i], file = self.type.read(file)
return res, file
def write(self, file, item):
def write(self, file, item):
return file, struct.pack(self.desc, item)
+@memoize.fast_memoize_multiple_args
class IntType(Type):
__slots__ = 'bytes step format_str max'.split(' ')
def get_record(fields):
fields = tuple(sorted(fields))
- if 'keys' in fields:
+ if 'keys' in fields or '_packed_size' in fields:
raise ValueError()
if fields not in _record_types:
class _Record(object):
- __slots__ = fields
+ __slots__ = fields + ('_packed_size',)
+ def __init__(self):
+ self._packed_size = None
def __repr__(self):
return repr(dict(self))
def __getitem__(self, key):
def __setitem__(self, key, value):
setattr(self, key, value)
#def __iter__(self):
- # for field in self.__slots__:
+ # for field in fields:
# yield field, getattr(self, field)
def keys(self):
- return self.__slots__
+ return fields
def get(self, key, default=None):
return getattr(self, key, default)
def __eq__(self, other):
if isinstance(other, dict):
return dict(self) == other
elif isinstance(other, _Record):
- return all(self[k] == other[k] for k in self.keys())
+ for k in fields:
+ if getattr(self, k) != getattr(other, k):
+ return False
+ return True
elif other is None:
return False
raise TypeError()
def __ne__(self, other):
return not (self == other)
_record_types[fields] = _Record
- return _record_types[fields]()
+ return _record_types[fields]
class ComposedType(Type):
def __init__(self, fields):
- self.fields = tuple(fields)
+ self.fields = list(fields)
self.field_names = set(k for k, v in fields)
+ self.record_type = get_record(k for k, v in self.fields)
def read(self, file):
- item = get_record(k for k, v in self.fields)
+ item = self.record_type()
for key, type_ in self.fields:
item[key], file = type_.read(file)
return item, file