OLD | NEW |
---|---|
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 Loading... | |
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 # Serialize the unions value and either | |
238 # 1. Return the serialized value itself as entry. | |
239 # 2. Append the serialized value to data and return 8 a pointer to the | |
240 # serialized value. (Assumes the data will immediately follow the union.) | |
241 (entry, handles) = field.field_type.Serialize( | |
242 union.data, 8, data, handle_offset) | |
243 | |
244 # If the value contained in the union is itself a union, we append its | |
245 # serialized value to data and set entry to 8, a pointer to the data. | |
246 if field.field_type.IsUnion(): | |
247 nested_union = bytearray(16) | |
248 HEADER_STRUCT.pack_into(nested_union, 0, entry[0], entry[1]) | |
249 POINTER_STRUCT.pack_into(nested_union, 8, entry[2]) | |
250 | |
251 data = nested_union + data | |
252 entry = 8 | |
253 | |
254 return (16, union.tag, entry, data), handles | |
255 | |
256 def Serialize(self, union, handle_offset): | |
257 (size, tag, entry, extra_data), handles = self.SerializeInline( | |
258 union, handle_offset) | |
259 data = bytearray(16) | |
260 data.extend(extra_data) | |
261 | |
262 field = self._fields[union.tag] | |
263 | |
264 HEADER_STRUCT.pack_into(data, 0, size, tag) | |
265 typecode = field.GetTypeCode() | |
266 | |
267 # If the value is a nested union, we store a 64 bits pointer to it. | |
268 if field.field_type.IsUnion(): | |
269 typecode = 'Q' | |
270 | |
271 struct.pack_into('<%s' % typecode, data, 8, entry) | |
272 return data, handles | |
273 | |
274 def Deserialize(self, context, union_class): | |
275 if len(context.data) < HEADER_STRUCT.size: | |
276 raise DeserializationException( | |
277 'Available data too short to contain header.') | |
278 (size, tag) = HEADER_STRUCT.unpack_from(context.data) | |
279 if size == 0: | |
280 return None | |
281 | |
282 if size != 16: | |
283 raise DeserializationException('Invalid union size %s' % size) | |
284 | |
285 field = self._fields[tag] | |
qsr
2015/07/20 21:29:59
1) You should not be using private variable outsid
azani
2015/07/20 22:17:52
Done.
| |
286 if field.field_type.IsUnion(): | |
287 ptr = POINTER_STRUCT.unpack_from(context.data, 8)[0] | |
288 value = field.field_type.Deserialize(ptr, context.GetSubContext(ptr+8)) | |
289 else: | |
290 raw_value = struct.unpack_from( | |
291 field.GetTypeCode(), context.data, 8)[0] | |
292 value = field.field_type.Deserialize(raw_value, context.GetSubContext(8)) | |
293 | |
294 union = union_class.__new__(union_class) | |
295 union._cur_field = field | |
296 union._data = value | |
297 return union | |
OLD | NEW |