| Index: mojo/public/python/mojo/bindings/descriptor.py
|
| diff --git a/mojo/public/python/mojo/bindings/descriptor.py b/mojo/public/python/mojo/bindings/descriptor.py
|
| index 06d636b7db6631d4d2d0fe41ab2aa68d17846469..1a466b8c6a661d10cb1c89ec4ba5a1caf0fc081f 100644
|
| --- a/mojo/public/python/mojo/bindings/descriptor.py
|
| +++ b/mojo/public/python/mojo/bindings/descriptor.py
|
| @@ -7,12 +7,9 @@
|
| """
|
|
|
| import array
|
| -import struct
|
|
|
| # pylint: disable=F0401
|
| -import mojo.bindings.serialization as serialization
|
| -import mojo.system
|
| -
|
| +from mojo.system import Handle
|
|
|
| class Type(object):
|
| """Describes the type of a struct field or a method parameter,"""
|
| @@ -32,44 +29,6 @@
|
| return self.Convert(value)
|
|
|
|
|
| -class SerializableType(Type):
|
| - """Describe a type that can be serialized by itself."""
|
| -
|
| - def __init__(self, typecode):
|
| - Type.__init__(self)
|
| - self.typecode = typecode
|
| - self.byte_size = struct.calcsize('=%s' % self.GetTypeCode())
|
| -
|
| - def GetTypeCode(self):
|
| - """
|
| - Returns the type code (as defined by the struct module) used to encode
|
| - this type.
|
| - """
|
| - return self.typecode
|
| -
|
| - def GetByteSize(self):
|
| - """
|
| - Returns the size of the encoding of this type.
|
| - """
|
| - return self.byte_size
|
| -
|
| - def Serialize(self, value, data_offset, data, handle_offset):
|
| - """
|
| - Serialize an value of this type.
|
| -
|
| - Args:
|
| - value: the value to serialize.
|
| - data_offset: the offset to the end of the data bytearray. Used to encode
|
| - pointers.
|
| - data: the bytearray to append additional data to.
|
| - handle_offset: the offset to use to encode handles.
|
| -
|
| - Returns a a tuple where the first element is the value to encode, and the
|
| - second is the array of handles to add to the message.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| -
|
| class BooleanType(Type):
|
| """Type object for booleans"""
|
|
|
| @@ -77,26 +36,23 @@
|
| return bool(value)
|
|
|
|
|
| -class NumericType(SerializableType):
|
| +class NumericType(Type):
|
| """Base Type object for all numeric types"""
|
|
|
| def GetDefaultValue(self, value):
|
| if value is None:
|
| - return self.Convert(0)
|
| + return self.convert(0)
|
| return self.Convert(value)
|
| -
|
| - def Serialize(self, value, data_offset, data, handle_offset):
|
| - return (value, [])
|
|
|
|
|
| class IntegerType(NumericType):
|
| """Type object for integer types."""
|
|
|
| - def __init__(self, typecode):
|
| - NumericType.__init__(self, typecode)
|
| - size = 8 * self.byte_size
|
| - signed = typecode.islower()
|
| - if signed:
|
| + def __init__(self, size, signed):
|
| + NumericType.__init__(self)
|
| + self.size = size
|
| + self.signed = signed
|
| + if self.signed:
|
| self._min_value = -(1 << (size - 1))
|
| self._max_value = (1 << (size - 1)) - 1
|
| else:
|
| @@ -117,6 +73,10 @@
|
| class FloatType(NumericType):
|
| """Type object for floating point number types."""
|
|
|
| + def __init__(self, size):
|
| + NumericType.__init__(self)
|
| + self.size = size
|
| +
|
| def Convert(self, value):
|
| if value is None:
|
| raise TypeError('None is not an floating point number.')
|
| @@ -125,27 +85,7 @@
|
| return float(value)
|
|
|
|
|
| -class PointerType(SerializableType):
|
| - """Base Type object for pointers."""
|
| -
|
| - def __init__(self, nullable=False):
|
| - SerializableType.__init__(self, 'Q')
|
| - self.nullable = nullable
|
| -
|
| - def Serialize(self, value, data_offset, data, handle_offset):
|
| - if value is None and not self.nullable:
|
| - raise serialization.SerializationException(
|
| - "Trying to serialize null for non nullable type.")
|
| - if value is None:
|
| - return (0, [])
|
| - return self.SerializePointer(value, data_offset, data, handle_offset)
|
| -
|
| - def SerializePointer(self, value, data_offset, data, handle_offset):
|
| - """Serialize the not null value."""
|
| - raise NotImplementedError()
|
| -
|
| -
|
| -class StringType(PointerType):
|
| +class StringType(Type):
|
| """
|
| Type object for strings.
|
|
|
| @@ -154,8 +94,8 @@
|
| """
|
|
|
| def __init__(self, nullable=False):
|
| - PointerType.__init__(self, nullable)
|
| - self._array_type = NativeArrayType('B', nullable)
|
| + Type.__init__(self)
|
| + self.nullable = nullable
|
|
|
| def Convert(self, value):
|
| if value is None or isinstance(value, unicode):
|
| @@ -164,76 +104,36 @@
|
| return unicode(value)
|
| raise TypeError('%r is not a string' % value)
|
|
|
| - def SerializePointer(self, value, data_offset, data, handle_offset):
|
| - string_array = array.array('b')
|
| - string_array.fromstring(value.encode('utf8'))
|
| - return self._array_type.SerializeArray(
|
| - string_array, data_offset, data, handle_offset)
|
| -
|
| -
|
| -class HandleType(SerializableType):
|
| +
|
| +class HandleType(Type):
|
| """Type object for handles."""
|
|
|
| def __init__(self, nullable=False):
|
| - SerializableType.__init__(self, 'i')
|
| - self.nullable = nullable
|
| -
|
| - def Convert(self, value):
|
| - if value is None:
|
| - return mojo.system.Handle()
|
| - if not isinstance(value, mojo.system.Handle):
|
| + Type.__init__(self)
|
| + self.nullable = nullable
|
| +
|
| + def Convert(self, value):
|
| + if value is None:
|
| + return Handle()
|
| + if not isinstance(value, Handle):
|
| raise TypeError('%r is not a handle' % value)
|
| return value
|
|
|
| - def Serialize(self, value, data_offset, data, handle_offset):
|
| - if not value.IsValid() and not self.nullable:
|
| - raise serialization.SerializationException(
|
| - "Trying to serialize null for non nullable type.")
|
| - if not value.IsValid():
|
| - return (-1, [])
|
| - return (handle_offset, [value])
|
| -
|
| -
|
| -class BaseArrayType(PointerType):
|
| +
|
| +class GenericArrayType(Type):
|
| """Abstract Type object for arrays."""
|
|
|
| def __init__(self, nullable=False, length=0):
|
| - PointerType.__init__(self, nullable)
|
| + Type.__init__(self)
|
| + self.nullable = nullable
|
| self.length = length
|
|
|
| - def SerializePointer(self, value, data_offset, data, handle_offset):
|
| - if self.length != 0 and len(value) != self.length:
|
| - raise serialization.SerializationException("Incorrect array size")
|
| - return self.SerializeArray(value, data_offset, data, handle_offset)
|
| -
|
| - def SerializeArray(self, value, data_offset, data, handle_offset):
|
| - """Serialize the not null array."""
|
| - raise NotImplementedError()
|
| -
|
| -class BooleanArrayType(BaseArrayType):
|
| -
|
| - def __init__(self, nullable=False, length=0):
|
| - BaseArrayType.__init__(self, nullable, length)
|
| - self._array_type = NativeArrayType('B', nullable)
|
| -
|
| - def Convert(self, value):
|
| - if value is None:
|
| - return value
|
| - return [TYPE_BOOL.Convert(x) for x in value]
|
| -
|
| - def SerializeArray(self, value, data_offset, data, handle_offset):
|
| - groups = [value[i:i+8] for i in range(0, len(value), 8)]
|
| - converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups])
|
| - return self._array_type.SerializeArray(
|
| - converted, data_offset, data, handle_offset)
|
| -
|
| -
|
| -class GenericArrayType(BaseArrayType):
|
| +
|
| +class PointerArrayType(GenericArrayType):
|
| """Type object for arrays of pointers."""
|
|
|
| def __init__(self, sub_type, nullable=False, length=0):
|
| - BaseArrayType.__init__(self, nullable, length)
|
| - assert isinstance(sub_type, SerializableType)
|
| + GenericArrayType.__init__(self, nullable, length)
|
| self.sub_type = sub_type
|
|
|
| def Convert(self, value):
|
| @@ -241,65 +141,27 @@
|
| return value
|
| return [self.sub_type.Convert(x) for x in value]
|
|
|
| - def SerializeArray(self, value, data_offset, data, handle_offset):
|
| - size = (serialization.HEADER_STRUCT.size +
|
| - self.sub_type.GetByteSize() * len(value))
|
| - data_end = len(data)
|
| - position = len(data) - data_offset
|
| - data.extend(bytearray(size +
|
| - serialization.NeededPaddingForAlignment(size)))
|
| - returned_handles = []
|
| - to_pack = []
|
| - position = position + 2
|
| - for item in value:
|
| - (new_data, new_handles) = self.sub_type.Serialize(
|
| - item,
|
| - len(data) - position,
|
| - data,
|
| - handle_offset + len(returned_handles))
|
| - to_pack.append(new_data)
|
| - returned_handles.extend(new_handles)
|
| - position = position + self.sub_type.GetByteSize()
|
| - serialization.HEADER_STRUCT.pack_into(data, data_end, size, len(value))
|
| - struct.pack_into("%d%s" % (len(value), self.sub_type.GetTypeCode()),
|
| - data,
|
| - data_end + serialization.HEADER_STRUCT.size,
|
| - *to_pack)
|
| - return (data_offset, returned_handles)
|
| -
|
| -
|
| -class NativeArrayType(BaseArrayType):
|
| +
|
| +class NativeArrayType(GenericArrayType):
|
| """Type object for arrays of native types."""
|
|
|
| def __init__(self, typecode, nullable=False, length=0):
|
| - BaseArrayType.__init__(self, nullable, length)
|
| - self.array_typecode = typecode
|
| -
|
| - def Convert(self, value):
|
| - if value is None:
|
| - return value
|
| - if (isinstance(value, array.array) and
|
| - value.array_typecode == self.array_typecode):
|
| - return value
|
| - return array.array(self.array_typecode, value)
|
| -
|
| - def SerializeArray(self, value, data_offset, data, handle_offset):
|
| - data_size = len(data)
|
| - data.extend(bytearray(serialization.HEADER_STRUCT.size))
|
| - data.extend(value.tostring())
|
| - data_length = len(data) - data_size
|
| - data.extend(bytearray(
|
| - serialization.NeededPaddingForAlignment(data_length)))
|
| - serialization.HEADER_STRUCT.pack_into(
|
| - data, data_size, data_length, len(value))
|
| - return (data_offset, [])
|
| -
|
| -
|
| -class StructType(PointerType):
|
| + GenericArrayType.__init__(self, nullable, length)
|
| + self.typecode = typecode
|
| +
|
| + def Convert(self, value):
|
| + if value is None:
|
| + return value
|
| + if isinstance(value, array.array) and value.typecode == self.typecode:
|
| + return value
|
| + return array.array(self.typecode, value)
|
| +
|
| +
|
| +class StructType(Type):
|
| """Type object for structs."""
|
|
|
| def __init__(self, struct_type, nullable=False):
|
| - PointerType.__init__(self)
|
| + Type.__init__(self)
|
| self.struct_type = struct_type
|
| self.nullable = nullable
|
|
|
| @@ -313,41 +175,30 @@
|
| return self.struct_type()
|
| return None
|
|
|
| - def SerializePointer(self, value, data_offset, data, handle_offset):
|
| - (new_data, new_handles) = value.Serialize(handle_offset)
|
| - data.extend(new_data)
|
| - return (data_offset, new_handles)
|
| -
|
| -
|
| -class NoneType(SerializableType):
|
| +
|
| +class NoneType(Type):
|
| """Placeholder type, used temporarily until all mojo types are handled."""
|
|
|
| - def __init__(self):
|
| - SerializableType.__init__(self, 'B')
|
| -
|
| def Convert(self, value):
|
| return None
|
|
|
| - def Serialize(self, value, data_offset, data, handle_offset):
|
| - return (0, [])
|
| -
|
|
|
| TYPE_NONE = NoneType()
|
|
|
| TYPE_BOOL = BooleanType()
|
|
|
| -TYPE_INT8 = IntegerType('b')
|
| -TYPE_INT16 = IntegerType('h')
|
| -TYPE_INT32 = IntegerType('i')
|
| -TYPE_INT64 = IntegerType('q')
|
| -
|
| -TYPE_UINT8 = IntegerType('B')
|
| -TYPE_UINT16 = IntegerType('H')
|
| -TYPE_UINT32 = IntegerType('I')
|
| -TYPE_UINT64 = IntegerType('Q')
|
| -
|
| -TYPE_FLOAT = FloatType('f')
|
| -TYPE_DOUBLE = FloatType('d')
|
| +TYPE_INT8 = IntegerType(8, True)
|
| +TYPE_INT16 = IntegerType(16, True)
|
| +TYPE_INT32 = IntegerType(32, True)
|
| +TYPE_INT64 = IntegerType(64, True)
|
| +
|
| +TYPE_UINT8 = IntegerType(8, False)
|
| +TYPE_UINT16 = IntegerType(16, False)
|
| +TYPE_UINT32 = IntegerType(32, False)
|
| +TYPE_UINT64 = IntegerType(64, False)
|
| +
|
| +TYPE_FLOAT = FloatType(4)
|
| +TYPE_DOUBLE = FloatType(8)
|
|
|
| TYPE_STRING = StringType()
|
| TYPE_NULLABLE_STRING = StringType(True)
|
| @@ -359,83 +210,13 @@
|
| class FieldDescriptor(object):
|
| """Describes a field in a generated struct."""
|
|
|
| - def __init__(self, name, field_type, field_number, default_value=None):
|
| + def __init__(self, name, field_type, offset,
|
| + bit_offset=None, default_value=None):
|
| self.name = name
|
| self.field_type = field_type
|
| - self.field_number = field_number
|
| + self.offset = offset
|
| + self.bit_offset = bit_offset
|
| self._default_value = default_value
|
|
|
| def GetDefaultValue(self):
|
| return self.field_type.GetDefaultValue(self._default_value)
|
| -
|
| -
|
| -class FieldGroup(object):
|
| - """
|
| - Describe a list of field in the generated struct that must be
|
| - serialized/deserialized together.
|
| - """
|
| - def __init__(self, descriptors):
|
| - self.descriptors = descriptors
|
| -
|
| - def GetDescriptors(self):
|
| - return self.descriptors
|
| -
|
| - def GetTypeCode(self):
|
| - raise NotImplementedError()
|
| -
|
| - def GetByteSize(self):
|
| - raise NotImplementedError()
|
| -
|
| - def GetVersion(self):
|
| - raise NotImplementedError()
|
| -
|
| - def Serialize(self, obj, data_offset, data, handle_offset):
|
| - raise NotImplementedError()
|
| -
|
| -
|
| -class SingleFieldGroup(FieldGroup, FieldDescriptor):
|
| - """A FieldGroup that contains a single FieldDescriptor."""
|
| -
|
| - def __init__(self, name, field_type, field_number, default_value=None):
|
| - FieldDescriptor.__init__(
|
| - self, name, field_type, field_number, default_value)
|
| - FieldGroup.__init__(self, [self])
|
| -
|
| - def GetTypeCode(self):
|
| - return self.field_type.GetTypeCode()
|
| -
|
| - def GetByteSize(self):
|
| - return self.field_type.GetByteSize()
|
| -
|
| - def GetVersion(self):
|
| - return self.field_number
|
| -
|
| - def Serialize(self, obj, data_offset, data, handle_offset):
|
| - value = getattr(obj, self.name)
|
| - return self.field_type.Serialize(value, data_offset, data, handle_offset)
|
| -
|
| -
|
| -class BooleanGroup(FieldGroup):
|
| - """A FieldGroup to pack booleans."""
|
| - def __init__(self, descriptors):
|
| - FieldGroup.__init__(self, descriptors)
|
| - self.version = min([descriptor.field_number for descriptor in descriptors])
|
| -
|
| - def GetTypeCode(self):
|
| - return "B"
|
| -
|
| - def GetByteSize(self):
|
| - return 1
|
| -
|
| - def GetVersion(self):
|
| - return self.version
|
| -
|
| - def Serialize(self, obj, data_offset, data, handle_offset):
|
| - value = _ConvertBooleansToByte(
|
| - [getattr(obj, field.name) for field in self.GetDescriptors()])
|
| - return (value, [])
|
| -
|
| -
|
| -def _ConvertBooleansToByte(booleans):
|
| - """Pack a list of booleans into an integer."""
|
| - return reduce(lambda x, y: x * 2 + y, reversed(booleans), 0)
|
|
|