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) |