Commit d4a62b87 authored by erg's avatar erg Committed by Commit bot

Revert of mojo: Add deserialization to python structs. (patchset #3 id:40001...

Revert of mojo: Add deserialization to python structs. (patchset #3 id:40001 of https://codereview.chromium.org/578263003/)

Reason for revert:
New unit tests fail.

https://build.chromium.org/p/chromium.linux/builders/Linux%20Tests/builds/13695

Original issue's description:
> mojo: Add deserialization to python structs.
>
> BUG=415491
> R=sdefresne@chromium.org,cmasone@chromium.org
>
> Committed: https://crrev.com/ea8a6ef576c314506c4b3ee25544f6bcaa895fe1
> Cr-Commit-Position: refs/heads/master@{#295478}

TBR=cmasone@chromium.org,sdefresne@chromium.org,qsr@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=415491

Review URL: https://codereview.chromium.org/579383002

Cr-Commit-Position: refs/heads/master@{#295522}
parent 53f608b5
...@@ -7,7 +7,6 @@ The descriptors used to define generated elements of the mojo python bindings. ...@@ -7,7 +7,6 @@ The descriptors used to define generated elements of the mojo python bindings.
""" """
import array import array
import itertools
import struct import struct
# pylint: disable=F0401 # pylint: disable=F0401
...@@ -56,7 +55,7 @@ class SerializableType(Type): ...@@ -56,7 +55,7 @@ class SerializableType(Type):
def Serialize(self, value, data_offset, data, handle_offset): def Serialize(self, value, data_offset, data, handle_offset):
""" """
Serialize a value of this type. Serialize an value of this type.
Args: Args:
value: the value to serialize. value: the value to serialize.
...@@ -70,21 +69,6 @@ class SerializableType(Type): ...@@ -70,21 +69,6 @@ class SerializableType(Type):
""" """
raise NotImplementedError() raise NotImplementedError()
def Deserialize(self, value, data, handles):
"""
Deserialize a value of this type.
Args:
value: the base value for this type. This is always a numeric type, and
corresponds to the first element in the tuple returned by
Serialize.
data: the bytearray to retrieve additional data from.
handles: the array of handles contained in the message to deserialize.
Returns the deserialized value.
"""
raise NotImplementedError()
class BooleanType(Type): class BooleanType(Type):
"""Type object for booleans""" """Type object for booleans"""
...@@ -104,9 +88,6 @@ class NumericType(SerializableType): ...@@ -104,9 +88,6 @@ class NumericType(SerializableType):
def Serialize(self, value, data_offset, data, handle_offset): def Serialize(self, value, data_offset, data, handle_offset):
return (value, []) return (value, [])
def Deserialize(self, value, data, handles):
return value
class IntegerType(NumericType): class IntegerType(NumericType):
"""Type object for integer types.""" """Type object for integer types."""
...@@ -154,28 +135,15 @@ class PointerType(SerializableType): ...@@ -154,28 +135,15 @@ class PointerType(SerializableType):
def Serialize(self, value, data_offset, data, handle_offset): def Serialize(self, value, data_offset, data, handle_offset):
if value is None and not self.nullable: if value is None and not self.nullable:
raise serialization.SerializationException( raise serialization.SerializationException(
'Trying to serialize null for non nullable type.') "Trying to serialize null for non nullable type.")
if value is None: if value is None:
return (0, []) return (0, [])
return self.SerializePointer(value, data_offset, data, handle_offset) return self.SerializePointer(value, data_offset, data, handle_offset)
def Deserialize(self, value, data, handles):
if value == 0:
if not self.nullable:
raise serialization.DeserializationException(
'Trying to deserialize null for non nullable type.')
return None
pointed_data = data[value:]
(size, nb_elements) = serialization.HEADER_STRUCT.unpack_from(pointed_data)
return self.DeserializePointer(size, nb_elements, pointed_data, handles)
def SerializePointer(self, value, data_offset, data, handle_offset): def SerializePointer(self, value, data_offset, data, handle_offset):
"""Serialize the not null value.""" """Serialize the not null value."""
raise NotImplementedError() raise NotImplementedError()
def DeserializePointer(self, size, nb_elements, data, handles):
raise NotImplementedError()
class StringType(PointerType): class StringType(PointerType):
""" """
...@@ -202,11 +170,6 @@ class StringType(PointerType): ...@@ -202,11 +170,6 @@ class StringType(PointerType):
return self._array_type.SerializeArray( return self._array_type.SerializeArray(
string_array, data_offset, data, handle_offset) string_array, data_offset, data, handle_offset)
def DeserializePointer(self, size, nb_elements, data, handles):
string_array = self._array_type.DeserializeArray(
size, nb_elements, data, handles)
return unicode(string_array.tostring(), 'utf8')
class HandleType(SerializableType): class HandleType(SerializableType):
"""Type object for handles.""" """Type object for handles."""
...@@ -225,20 +188,11 @@ class HandleType(SerializableType): ...@@ -225,20 +188,11 @@ class HandleType(SerializableType):
def Serialize(self, value, data_offset, data, handle_offset): def Serialize(self, value, data_offset, data, handle_offset):
if not value.IsValid() and not self.nullable: if not value.IsValid() and not self.nullable:
raise serialization.SerializationException( raise serialization.SerializationException(
'Trying to serialize null for non nullable type.') "Trying to serialize null for non nullable type.")
if not value.IsValid(): if not value.IsValid():
return (-1, []) return (-1, [])
return (handle_offset, [value]) return (handle_offset, [value])
def Deserialize(self, value, data, handles):
if value == -1:
if not self.nullable:
raise serialization.DeserializationException(
'Trying to deserialize null for non nullable type.')
return mojo.system.Handle()
# TODO(qsr) validate handle order
return handles[value]
class BaseArrayType(PointerType): class BaseArrayType(PointerType):
"""Abstract Type object for arrays.""" """Abstract Type object for arrays."""
...@@ -249,22 +203,13 @@ class BaseArrayType(PointerType): ...@@ -249,22 +203,13 @@ class BaseArrayType(PointerType):
def SerializePointer(self, value, data_offset, data, handle_offset): def SerializePointer(self, value, data_offset, data, handle_offset):
if self.length != 0 and len(value) != self.length: if self.length != 0 and len(value) != self.length:
raise serialization.SerializationException('Incorrect array size') raise serialization.SerializationException("Incorrect array size")
return self.SerializeArray(value, data_offset, data, handle_offset) return self.SerializeArray(value, data_offset, data, handle_offset)
def SerializeArray(self, value, data_offset, data, handle_offset): def SerializeArray(self, value, data_offset, data, handle_offset):
"""Serialize the not null array.""" """Serialize the not null array."""
raise NotImplementedError() raise NotImplementedError()
def DeserializePointer(self, size, nb_elements, data, handles):
if self.length != 0 and size != self.length:
raise serialization.DeserializationException('Incorrect array size')
return self.DeserializeArray(size, nb_elements, data, handles)
def DeserializeArray(self, size, nb_elements, data, handles):
raise NotImplementedError()
class BooleanArrayType(BaseArrayType): class BooleanArrayType(BaseArrayType):
def __init__(self, nullable=False, length=0): def __init__(self, nullable=False, length=0):
...@@ -279,17 +224,8 @@ class BooleanArrayType(BaseArrayType): ...@@ -279,17 +224,8 @@ class BooleanArrayType(BaseArrayType):
def SerializeArray(self, value, data_offset, data, handle_offset): def SerializeArray(self, value, data_offset, data, handle_offset):
groups = [value[i:i+8] for i in range(0, len(value), 8)] groups = [value[i:i+8] for i in range(0, len(value), 8)]
converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups]) converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups])
return _SerializeNativeArray(converted, data_offset, data, len(value)) return self._array_type.SerializeArray(
converted, data_offset, data, handle_offset)
def DeserializeArray(self, size, nb_elements, data, handles):
converted = self._array_type.DeserializeArray(
size, nb_elements, data, handles)
elements = list(itertools.islice(
itertools.chain.from_iterable(
[_ConvertByteToBooleans(x, 8) for x in converted]),
0,
nb_elements))
return elements
class GenericArrayType(BaseArrayType): class GenericArrayType(BaseArrayType):
...@@ -309,11 +245,12 @@ class GenericArrayType(BaseArrayType): ...@@ -309,11 +245,12 @@ class GenericArrayType(BaseArrayType):
size = (serialization.HEADER_STRUCT.size + size = (serialization.HEADER_STRUCT.size +
self.sub_type.GetByteSize() * len(value)) self.sub_type.GetByteSize() * len(value))
data_end = len(data) data_end = len(data)
position = len(data) + serialization.HEADER_STRUCT.size position = len(data) - data_offset
data.extend(bytearray(size + data.extend(bytearray(size +
serialization.NeededPaddingForAlignment(size))) serialization.NeededPaddingForAlignment(size)))
returned_handles = [] returned_handles = []
to_pack = [] to_pack = []
position = position + 2
for item in value: for item in value:
(new_data, new_handles) = self.sub_type.Serialize( (new_data, new_handles) = self.sub_type.Serialize(
item, item,
...@@ -324,23 +261,12 @@ class GenericArrayType(BaseArrayType): ...@@ -324,23 +261,12 @@ class GenericArrayType(BaseArrayType):
returned_handles.extend(new_handles) returned_handles.extend(new_handles)
position = position + self.sub_type.GetByteSize() position = position + self.sub_type.GetByteSize()
serialization.HEADER_STRUCT.pack_into(data, data_end, size, len(value)) serialization.HEADER_STRUCT.pack_into(data, data_end, size, len(value))
struct.pack_into('%d%s' % (len(value), self.sub_type.GetTypeCode()), struct.pack_into("%d%s" % (len(value), self.sub_type.GetTypeCode()),
data, data,
data_end + serialization.HEADER_STRUCT.size, data_end + serialization.HEADER_STRUCT.size,
*to_pack) *to_pack)
return (data_offset, returned_handles) return (data_offset, returned_handles)
def DeserializeArray(self, size, nb_elements, data, handles):
values = struct.unpack_from(
'%d%s' % (nb_elements, self.sub_type.GetTypeCode()),
data[serialization.HEADER_STRUCT.size:])
result = []
position = serialization.HEADER_STRUCT.size
for value in values:
result.append(self.sub_type.Deserialize(value, data[position:], handles))
position += self.sub_type.GetByteSize()
return result
class NativeArrayType(BaseArrayType): class NativeArrayType(BaseArrayType):
"""Type object for arrays of native types.""" """Type object for arrays of native types."""
...@@ -358,12 +284,15 @@ class NativeArrayType(BaseArrayType): ...@@ -358,12 +284,15 @@ class NativeArrayType(BaseArrayType):
return array.array(self.array_typecode, value) return array.array(self.array_typecode, value)
def SerializeArray(self, value, data_offset, data, handle_offset): def SerializeArray(self, value, data_offset, data, handle_offset):
return _SerializeNativeArray(value, data_offset, data, len(value)) data_size = len(data)
data.extend(bytearray(serialization.HEADER_STRUCT.size))
def DeserializeArray(self, size, nb_elements, data, handles): data.extend(value.tostring())
result = array.array(self.array_typecode) data_length = len(data) - data_size
result.fromstring(data[serialization.HEADER_STRUCT.size:size].tobytes()) data.extend(bytearray(
return result serialization.NeededPaddingForAlignment(data_length)))
serialization.HEADER_STRUCT.pack_into(
data, data_size, data_length, len(value))
return (data_offset, [])
class StructType(PointerType): class StructType(PointerType):
...@@ -389,9 +318,6 @@ class StructType(PointerType): ...@@ -389,9 +318,6 @@ class StructType(PointerType):
data.extend(new_data) data.extend(new_data)
return (data_offset, new_handles) return (data_offset, new_handles)
def DeserializePointer(self, size, nb_elements, data, handles):
return self.struct_type.Deserialize(data, handles)
class NoneType(SerializableType): class NoneType(SerializableType):
"""Placeholder type, used temporarily until all mojo types are handled.""" """Placeholder type, used temporarily until all mojo types are handled."""
...@@ -405,9 +331,6 @@ class NoneType(SerializableType): ...@@ -405,9 +331,6 @@ class NoneType(SerializableType):
def Serialize(self, value, data_offset, data, handle_offset): def Serialize(self, value, data_offset, data, handle_offset):
return (0, []) return (0, [])
def Deserialize(self, value, data, handles):
return None
TYPE_NONE = NoneType() TYPE_NONE = NoneType()
...@@ -469,9 +392,6 @@ class FieldGroup(object): ...@@ -469,9 +392,6 @@ class FieldGroup(object):
def Serialize(self, obj, data_offset, data, handle_offset): def Serialize(self, obj, data_offset, data, handle_offset):
raise NotImplementedError() raise NotImplementedError()
def Deserialize(self, value, data, handles):
raise NotImplementedError()
class SingleFieldGroup(FieldGroup, FieldDescriptor): class SingleFieldGroup(FieldGroup, FieldDescriptor):
"""A FieldGroup that contains a single FieldDescriptor.""" """A FieldGroup that contains a single FieldDescriptor."""
...@@ -494,10 +414,6 @@ class SingleFieldGroup(FieldGroup, FieldDescriptor): ...@@ -494,10 +414,6 @@ class SingleFieldGroup(FieldGroup, FieldDescriptor):
value = getattr(obj, self.name) value = getattr(obj, self.name)
return self.field_type.Serialize(value, data_offset, data, handle_offset) return self.field_type.Serialize(value, data_offset, data, handle_offset)
def Deserialize(self, value, data, handles):
entity = self.field_type.Deserialize(value, data, handles)
return { self.name: entity }
class BooleanGroup(FieldGroup): class BooleanGroup(FieldGroup):
"""A FieldGroup to pack booleans.""" """A FieldGroup to pack booleans."""
...@@ -506,7 +422,7 @@ class BooleanGroup(FieldGroup): ...@@ -506,7 +422,7 @@ class BooleanGroup(FieldGroup):
self.version = min([descriptor.field_number for descriptor in descriptors]) self.version = min([descriptor.field_number for descriptor in descriptors])
def GetTypeCode(self): def GetTypeCode(self):
return 'B' return "B"
def GetByteSize(self): def GetByteSize(self):
return 1 return 1
...@@ -519,33 +435,7 @@ class BooleanGroup(FieldGroup): ...@@ -519,33 +435,7 @@ class BooleanGroup(FieldGroup):
[getattr(obj, field.name) for field in self.GetDescriptors()]) [getattr(obj, field.name) for field in self.GetDescriptors()])
return (value, []) return (value, [])
def Deserialize(self, value, data, handles):
values = itertools.izip_longest([x.name for x in self.descriptors],
_ConvertByteToBooleans(value),
fillvalue=False)
return dict(values)
def _SerializeNativeArray(value, data_offset, data, length):
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, length)
return (data_offset, [])
def _ConvertBooleansToByte(booleans): def _ConvertBooleansToByte(booleans):
"""Pack a list of booleans into an integer.""" """Pack a list of booleans into an integer."""
return reduce(lambda x, y: x * 2 + y, reversed(booleans), 0) return reduce(lambda x, y: x * 2 + y, reversed(booleans), 0)
def _ConvertByteToBooleans(value, min_size=0):
"Unpack an integer into a list of booleans."""
res = []
while value:
res.append(bool(value&1))
value = value / 2
res.extend([False] * (min_size - len(res)))
return res
...@@ -107,14 +107,6 @@ class MojoStructType(type): ...@@ -107,14 +107,6 @@ class MojoStructType(type):
return serialization_object.Serialize(self, handle_offset) return serialization_object.Serialize(self, handle_offset)
dictionary['Serialize'] = Serialize dictionary['Serialize'] = Serialize
def Deserialize(cls, data, handles):
result = cls.__new__(cls)
fields = {}
serialization_object.Deserialize(fields, data, handles)
result._fields = fields
return result
dictionary['Deserialize'] = classmethod(Deserialize)
return type.__new__(mcs, name, bases, dictionary) return type.__new__(mcs, name, bases, dictionary)
# Prevent adding new attributes, or mutating constants. # Prevent adding new attributes, or mutating constants.
......
...@@ -16,42 +16,28 @@ class SerializationException(Exception): ...@@ -16,42 +16,28 @@ class SerializationException(Exception):
pass pass
class DeserializationException(Exception):
"""Error when strying to deserialize a struct."""
pass
class Serialization(object): class Serialization(object):
""" """
Helper class to serialize/deserialize a struct. Helper class to serialize/deserialize a struct.
""" """
def __init__(self, groups): def __init__(self, groups):
self.version = _GetVersion(groups)
self._groups = groups self._groups = groups
self.version = _GetVersion(groups)
main_struct = _GetStruct(groups) main_struct = _GetStruct(groups)
self.size = HEADER_STRUCT.size + main_struct.size self.size = HEADER_STRUCT.size + main_struct.size
self._struct_per_version = { self._struct_per_version = {
self.version: main_struct, self.version: main_struct,
}
self._groups_per_version = {
self.version: groups,
} }
def _GetMainStruct(self): def _GetMainStruct(self):
return self._GetStruct(self.version) return self._GetStruct(self.version)
def _GetGroups(self, version):
# If asking for a version greater than the last known.
version = min(version, self.version)
if version not in self._groups_per_version:
self._groups_per_version[version] = _FilterGroups(self._groups, version)
return self._groups_per_version[version]
def _GetStruct(self, version): def _GetStruct(self, version):
# If asking for a version greater than the last known. # If asking for a greater ver
version = min(version, self.version) version = min(version, self.version)
if version not in self._struct_per_version: if version not in self._struct_per_version:
self._struct_per_version[version] = _GetStruct(self._GetGroups(version)) self._struct_per_version[version] = _GetStruct(_FilterGroups(self._groups,
version))
return self._struct_per_version[version] return self._struct_per_version[version]
def Serialize(self, obj, handle_offset): def Serialize(self, obj, handle_offset):
...@@ -78,18 +64,6 @@ class Serialization(object): ...@@ -78,18 +64,6 @@ class Serialization(object):
self._GetMainStruct().pack_into(data, HEADER_STRUCT.size, *to_pack) self._GetMainStruct().pack_into(data, HEADER_STRUCT.size, *to_pack)
return (data, handles) return (data, handles)
def Deserialize(self, fields, data, handles):
(_, version) = HEADER_STRUCT.unpack_from(data)
version_struct = self._GetStruct(version)
entitities = version_struct.unpack_from(data, HEADER_STRUCT.size)
filtered_groups = self._GetGroups(version)
position = HEADER_STRUCT.size
for (group, value) in zip(filtered_groups, entitities):
position = position + NeededPaddingForAlignment(position,
group.GetByteSize())
fields.update(group.Deserialize(value, data[position:], handles))
position += group.GetByteSize()
def NeededPaddingForAlignment(value, alignment=8): def NeededPaddingForAlignment(value, alignment=8):
"""Returns the padding necessary to align value with the given alignment.""" """Returns the padding necessary to align value with the given alignment."""
...@@ -103,7 +77,7 @@ def _GetVersion(groups): ...@@ -103,7 +77,7 @@ def _GetVersion(groups):
def _FilterGroups(groups, version): def _FilterGroups(groups, version):
return [group for group in groups if group.GetVersion() < version] return [group for group in groups if group.version < version]
def _GetStruct(groups): def _GetStruct(groups):
......
...@@ -2,67 +2,19 @@ ...@@ -2,67 +2,19 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import math
import unittest import unittest
# pylint: disable=F0401 # pylint: disable=F0401
import mojo.bindings.reflection as reflection
import mojo.system import mojo.system
# Generated files # Generated files
# pylint: disable=F0401 # pylint: disable=F0401
import sample_import_mojom
import sample_import2_mojom
import sample_service_mojom import sample_service_mojom
def _NewHandle(): def _NewHandle():
return mojo.system.MessagePipe().handle0 return mojo.system.MessagePipe().handle0
def _TestEquality(x, y):
if x == y:
return True
if type(x) != type(y):
print '\n%r != %r. Element are not of the same type.' % (x, y)
return False
if isinstance(x, float) and math.isnan(x) and math.isnan(y):
return True
if hasattr(x, '__len__'):
if len(x) != len(y):
print '\n%r != %r. Iterables are not of the same size.' % (x, y)
return False
for (x1, y1) in zip(x, y):
if not _TestEquality(x1, y1):
return False
return True
if (hasattr(x, '__metaclass__') and
x.__metaclass__ == reflection.MojoStructType):
properties = [p for p in dir(x) if not p.startswith('_')]
for p in properties:
p1 = getattr(x, p)
p2 = getattr(y, p)
if not hasattr(p1, '__call__') and not _TestEquality(p1, p2):
print '\n%r != %r. Not equal for property %r.' % (x, y, p)
return False
return True
return False
def _NewBar():
bar_instance = sample_service_mojom.Bar()
bar_instance.alpha = 22
bar_instance.beta = 87
bar_instance.gamma = 122
bar_instance.type = sample_service_mojom.Bar.Type.BOTH
return bar_instance
def _NewFoo(): def _NewFoo():
foo_instance = sample_service_mojom.Foo() foo_instance = sample_service_mojom.Foo()
foo_instance.name = "Foo.name" foo_instance.name = "Foo.name"
...@@ -71,10 +23,10 @@ def _NewFoo(): ...@@ -71,10 +23,10 @@ def _NewFoo():
foo_instance.a = False foo_instance.a = False
foo_instance.b = True foo_instance.b = True
foo_instance.c = True foo_instance.c = True
foo_instance.bar = _NewBar() foo_instance.bar = sample_service_mojom.Bar()
foo_instance.extra_bars = [ foo_instance.extra_bars = [
_NewBar(), sample_service_mojom.Bar(),
_NewBar(), sample_service_mojom.Bar()
] ]
foo_instance.data = 'Hello world' foo_instance.data = 'Hello world'
foo_instance.source = _NewHandle() foo_instance.source = _NewHandle()
...@@ -89,43 +41,12 @@ def _NewFoo(): ...@@ -89,43 +41,12 @@ def _NewFoo():
], ],
[], [],
] ]
foo_instance.array_of_bools = [ True, 0, 1, 2, 0, 0, 0, 0, 0, True ] foo_instance.array_of_bools = [ True, 0, 1, 2, 0 ]
return foo_instance return foo_instance
class SerializationDeserializationTest(unittest.TestCase): class SerializationDeserializationTest(unittest.TestCase):
def testTestEquality(self):
self.assertFalse(_TestEquality(1, 2))
def testFooSerialization(self): def testFooSerialization(self):
(data, _) = _NewFoo().Serialize() (data, _) = _NewFoo().Serialize()
self.assertTrue(len(data)) self.assertTrue(len(data))
self.assertEquals(len(data) % 8, 0) self.assertEquals(len(data) % 8, 0)
def testFooDeserialization(self):
(data, handles) = _NewFoo().Serialize()
self.assertTrue(
sample_service_mojom.Foo.Deserialize(memoryview(data), handles))
def testFooSerializationDeserialization(self):
foo1 = _NewFoo()
(data, handles) = foo1.Serialize()
foo2 = sample_service_mojom.Foo.Deserialize(memoryview(data), handles)
self.assertTrue(_TestEquality(foo1, foo2))
def testDefaultsTestSerializationDeserialization(self):
v1 = sample_service_mojom.DefaultsTest()
v1.a18 = []
v1.a19 = ""
v1.a21 = sample_import_mojom.Point()
v1.a22.location = sample_import_mojom.Point()
v1.a22.size = sample_import2_mojom.Size()
(data, handles) = v1.Serialize()
v2 = sample_service_mojom.DefaultsTest.Deserialize(memoryview(data),
handles)
self.assertTrue(_TestEquality(v1, v2))
def testFooDeserializationError(self):
with self.assertRaises(Exception):
sample_service_mojom.Foo.Deserialize("", [])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment