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

Side by Side Diff: mojo/public/python/mojo_bindings/serialization.py

Issue 1218023006: Implement python mojo bindings unions. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 5 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 unified diff | Download patch
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Utility classes for serialization""" 5 """Utility classes for serialization"""
6 6
7 import struct 7 import struct
8 8
9 9
10 # Format of a header for a struct or an array. 10 # Format of a header for a struct, array or union.
11 HEADER_STRUCT = struct.Struct("<II") 11 HEADER_STRUCT = struct.Struct("<II")
12 12
13 # Format for a pointer.
14 POINTER_STRUCT = struct.Struct("<Q")
15
13 16
14 def Flatten(value): 17 def Flatten(value):
15 """Flattens nested lists/tuples into an one-level list. If value is not a 18 """Flattens nested lists/tuples into an one-level list. If value is not a
16 list/tuple, it is converted to an one-item list. For example, 19 list/tuple, it is converted to an one-item list. For example,
17 (1, 2, [3, 4, ('56', '7')]) is converted to [1, 2, 3, 4, '56', '7']; 20 (1, 2, [3, 4, ('56', '7')]) is converted to [1, 2, 3, 4, '56', '7'];
18 1 is converted to [1]. 21 1 is converted to [1].
19 """ 22 """
20 if isinstance(value, (list, tuple)): 23 if isinstance(value, (list, tuple)):
21 result = [] 24 result = []
22 for item in value: 25 for item in value:
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 needed_padding = NeededPaddingForAlignment(index, group.GetAlignment()) 214 needed_padding = NeededPaddingForAlignment(index, group.GetAlignment())
212 if needed_padding: 215 if needed_padding:
213 codes.append('x' * needed_padding) 216 codes.append('x' * needed_padding)
214 index = index + needed_padding 217 index = index + needed_padding
215 codes.append(code) 218 codes.append(code)
216 index = index + group.GetByteSize() 219 index = index + group.GetByteSize()
217 alignment_needed = NeededPaddingForAlignment(index) 220 alignment_needed = NeededPaddingForAlignment(index)
218 if alignment_needed: 221 if alignment_needed:
219 codes.append('x' * alignment_needed) 222 codes.append('x' * alignment_needed)
220 return struct.Struct(''.join(codes)) 223 return struct.Struct(''.join(codes))
224
225
226 class UnionSerializer(object):
227 """
228 Helper class to serialize/deserialize a union.
229 """
230 def __init__(self, fields):
231 self._fields = {field.index: field for field in fields}
232
233 def SerializeInline(self, union, handle_offset):
234 data = bytearray()
235 field = self._fields[union.tag]
236
237 # If the union value is a simple type or a nested union, it is returned as
238 # entry.
239 # Otherwise, the serialized value is appended to data and the value of entry
240 # is -1. The caller will need to set entry to the location where the
241 # caller will append data.
242 (entry, handles) = field.field_type.Serialize(
243 union.data, -1, data, handle_offset)
244
245 # If the value contained in the union is itself a union, we append its
246 # serialized value to data and set entry to -1. The caller will need to set
247 # entry to the location where the caller will append data.
248 if field.field_type.IsUnion():
249 nested_union = bytearray(16)
250 HEADER_STRUCT.pack_into(nested_union, 0, entry[0], entry[1])
251 POINTER_STRUCT.pack_into(nested_union, 8, entry[2])
252
253 data = nested_union + data
254
255 # Since we do not know where the caller will append the nested union,
256 # we set entry to an invalid value and let the caller figure out the right
257 # value.
258 entry = -1
259
260 return (16, union.tag, entry, data), handles
261
262 def Serialize(self, union, handle_offset):
263 (size, tag, entry, extra_data), handles = self.SerializeInline(
264 union, handle_offset)
265 data = bytearray(16)
266 if extra_data:
267 entry = 8
268 data.extend(extra_data)
269
270 field = self._fields[union.tag]
271
272 HEADER_STRUCT.pack_into(data, 0, size, tag)
273 typecode = field.GetTypeCode()
274
275 # If the value is a nested union, we store a 64 bits pointer to it.
276 if field.field_type.IsUnion():
277 typecode = 'Q'
278
279 struct.pack_into('<%s' % typecode, data, 8, entry)
280 return data, handles
281
282 def Deserialize(self, context, union_class):
283 if len(context.data) < HEADER_STRUCT.size:
284 raise DeserializationException(
285 'Available data too short to contain header.')
286 (size, tag) = HEADER_STRUCT.unpack_from(context.data)
287
288 if size == 0:
289 return None
290
291 if size != 16:
292 raise DeserializationException('Invalid union size %s' % size)
293
294 union = union_class.__new__(union_class)
295 if tag not in self._fields:
qsr 2015/07/20 23:08:27 Do the test pass? _fields is not in the union anym
azani 2015/07/20 23:12:13 This is the UnionSerializer class. You're thinking
qsr 2015/07/20 23:16:15 Oh. Sorry you are perfectly right.
296 union.SetInternals(None, None)
297 return union
298
299 field = self._fields[tag]
300 if field.field_type.IsUnion():
301 ptr = POINTER_STRUCT.unpack_from(context.data, 8)[0]
302 value = field.field_type.Deserialize(ptr, context.GetSubContext(ptr+8))
303 else:
304 raw_value = struct.unpack_from(
305 field.GetTypeCode(), context.data, 8)[0]
306 value = field.field_type.Deserialize(raw_value, context.GetSubContext(8))
307
308 union.SetInternals(field, value)
309 return union
OLDNEW
« no previous file with comments | « mojo/public/python/mojo_bindings/reflection.py ('k') | mojo/public/tools/bindings/generators/mojom_python_generator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698