Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Unified Diff: mojo/public/python/mojo/bindings/descriptor.py

Issue 578263003: mojo: Add deserialization to python structs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..42fb3a4da98888e34818b950cea0bf79abe828e2 100644
--- a/mojo/public/python/mojo/bindings/descriptor.py
+++ b/mojo/public/python/mojo/bindings/descriptor.py
@@ -7,6 +7,7 @@ The descriptors used to define generated elements of the mojo python bindings.
"""
import array
+import itertools
import struct
# pylint: disable=F0401
@@ -55,7 +56,7 @@ class SerializableType(Type):
def Serialize(self, value, data_offset, data, handle_offset):
"""
- Serialize an value of this type.
+ Serialize a value of this type.
Args:
value: the value to serialize.
@@ -69,6 +70,21 @@ class SerializableType(Type):
"""
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):
"""Type object for booleans"""
@@ -88,6 +104,9 @@ class NumericType(SerializableType):
def Serialize(self, value, data_offset, data, handle_offset):
return (value, [])
+ def Deserialize(self, value, data, handles):
+ return value
+
class IntegerType(NumericType):
"""Type object for integer types."""
@@ -135,15 +154,28 @@ class PointerType(SerializableType):
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.")
+ 'Trying to serialize null for non nullable type.')
if value is None:
return (0, [])
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):
"""Serialize the not null value."""
raise NotImplementedError()
+ def DeserializePointer(self, size, nb_elements, data, handles):
+ raise NotImplementedError()
+
class StringType(PointerType):
"""
@@ -170,6 +202,11 @@ class StringType(PointerType):
return self._array_type.SerializeArray(
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):
"""Type object for handles."""
@@ -188,11 +225,20 @@ class HandleType(SerializableType):
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.")
+ 'Trying to serialize null for non nullable type.')
if not value.IsValid():
return (-1, [])
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):
"""Abstract Type object for arrays."""
@@ -203,13 +249,22 @@ class BaseArrayType(PointerType):
def SerializePointer(self, value, data_offset, data, handle_offset):
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)
def SerializeArray(self, value, data_offset, data, handle_offset):
"""Serialize the not null array."""
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):
def __init__(self, nullable=False, length=0):
@@ -224,8 +279,17 @@ class BooleanArrayType(BaseArrayType):
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)
+ return _SerializeNativeArray(converted, data_offset, data, len(value))
+
+ 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):
@@ -245,12 +309,11 @@ class GenericArrayType(BaseArrayType):
size = (serialization.HEADER_STRUCT.size +
self.sub_type.GetByteSize() * len(value))
data_end = len(data)
- position = len(data) - data_offset
+ position = len(data) + serialization.HEADER_STRUCT.size
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,
@@ -261,12 +324,23 @@ class GenericArrayType(BaseArrayType):
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()),
+ 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)
+ 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):
"""Type object for arrays of native types."""
@@ -284,15 +358,12 @@ class NativeArrayType(BaseArrayType):
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, [])
+ return _SerializeNativeArray(value, data_offset, data, len(value))
+
+ def DeserializeArray(self, size, nb_elements, data, handles):
+ result = array.array(self.array_typecode)
+ result.fromstring(data[serialization.HEADER_STRUCT.size:size].tobytes())
+ return result
class StructType(PointerType):
@@ -318,6 +389,9 @@ class StructType(PointerType):
data.extend(new_data)
return (data_offset, new_handles)
+ def DeserializePointer(self, size, nb_elements, data, handles):
+ return self.struct_type.Deserialize(data, handles)
+
class NoneType(SerializableType):
"""Placeholder type, used temporarily until all mojo types are handled."""
@@ -331,6 +405,9 @@ class NoneType(SerializableType):
def Serialize(self, value, data_offset, data, handle_offset):
return (0, [])
+ def Deserialize(self, value, data, handles):
+ return None
sdefresne 2014/09/18 12:56:21 Don't you want to validate that the value is 0?
qsr 2014/09/18 14:16:36 Not really. NoneType is not there to stay. But I h
sdefresne 2014/09/18 15:01:49 Acknowledged.
+
TYPE_NONE = NoneType()
@@ -392,6 +469,9 @@ class FieldGroup(object):
def Serialize(self, obj, data_offset, data, handle_offset):
raise NotImplementedError()
+ def Deserialize(self, value, data, handles):
+ raise NotImplementedError()
+
class SingleFieldGroup(FieldGroup, FieldDescriptor):
"""A FieldGroup that contains a single FieldDescriptor."""
@@ -414,6 +494,10 @@ class SingleFieldGroup(FieldGroup, FieldDescriptor):
value = getattr(obj, self.name)
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):
"""A FieldGroup to pack booleans."""
@@ -422,7 +506,7 @@ class BooleanGroup(FieldGroup):
self.version = min([descriptor.field_number for descriptor in descriptors])
def GetTypeCode(self):
- return "B"
+ return 'B'
def GetByteSize(self):
return 1
@@ -435,7 +519,33 @@ class BooleanGroup(FieldGroup):
[getattr(obj, field.name) for field in self.GetDescriptors()])
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):
"""Pack a list of booleans into an integer."""
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
« no previous file with comments | « no previous file | mojo/public/python/mojo/bindings/reflection.py » ('j') | mojo/public/python/mojo/bindings/reflection.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698