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

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

Issue 814543006: Move //mojo/{public, edk} underneath //third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 11 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
« no previous file with comments | « mojo/public/python/mojo_bindings/reflection.py ('k') | mojo/public/python/mojo_system.pyx » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 # found in the LICENSE file.
4
5 """Utility classes for serialization"""
6
7 import struct
8
9
10 # Format of a header for a struct or an array.
11 HEADER_STRUCT = struct.Struct("<II")
12
13
14 class SerializationException(Exception):
15 """Error when strying to serialize a struct."""
16 pass
17
18
19 class DeserializationException(Exception):
20 """Error when strying to deserialize a struct."""
21 pass
22
23
24 class DeserializationContext(object):
25
26 def ClaimHandle(self, handle):
27 raise NotImplementedError()
28
29 def ClaimMemory(self, start, size):
30 raise NotImplementedError()
31
32 def GetSubContext(self, offset):
33 raise NotImplementedError()
34
35 def IsInitialContext(self):
36 raise NotImplementedError()
37
38
39 class RootDeserializationContext(DeserializationContext):
40 def __init__(self, data, handles):
41 if isinstance(data, buffer):
42 self.data = data
43 else:
44 self.data = buffer(data)
45 self._handles = handles
46 self._next_handle = 0;
47 self._next_memory = 0;
48
49 def ClaimHandle(self, handle):
50 if handle < self._next_handle:
51 raise DeserializationException('Accessing handles out of order.')
52 self._next_handle = handle + 1
53 return self._handles[handle]
54
55 def ClaimMemory(self, start, size):
56 if start < self._next_memory:
57 raise DeserializationException('Accessing buffer out of order.')
58 self._next_memory = start + size
59
60 def GetSubContext(self, offset):
61 return _ChildDeserializationContext(self, offset)
62
63 def IsInitialContext(self):
64 return True
65
66
67 class _ChildDeserializationContext(DeserializationContext):
68 def __init__(self, parent, offset):
69 self._parent = parent
70 self._offset = offset
71 self.data = buffer(parent.data, offset)
72
73 def ClaimHandle(self, handle):
74 return self._parent.ClaimHandle(handle)
75
76 def ClaimMemory(self, start, size):
77 return self._parent.ClaimMemory(self._offset + start, size)
78
79 def GetSubContext(self, offset):
80 return self._parent.GetSubContext(self._offset + offset)
81
82 def IsInitialContext(self):
83 return False
84
85
86 class Serialization(object):
87 """
88 Helper class to serialize/deserialize a struct.
89 """
90 def __init__(self, groups):
91 self.version = _GetVersion(groups)
92 self._groups = groups
93 main_struct = _GetStruct(groups)
94 self.size = HEADER_STRUCT.size + main_struct.size
95 self._struct_per_version = {
96 self.version: main_struct,
97 }
98 self._groups_per_version = {
99 self.version: groups,
100 }
101
102 def _GetMainStruct(self):
103 return self._GetStruct(self.version)
104
105 def _GetGroups(self, version):
106 # If asking for a version greater than the last known.
107 version = min(version, self.version)
108 if version not in self._groups_per_version:
109 self._groups_per_version[version] = _FilterGroups(self._groups, version)
110 return self._groups_per_version[version]
111
112 def _GetStruct(self, version):
113 # If asking for a version greater than the last known.
114 version = min(version, self.version)
115 if version not in self._struct_per_version:
116 self._struct_per_version[version] = _GetStruct(self._GetGroups(version))
117 return self._struct_per_version[version]
118
119 def Serialize(self, obj, handle_offset):
120 """
121 Serialize the given obj. handle_offset is the the first value to use when
122 encoding handles.
123 """
124 handles = []
125 data = bytearray(self.size)
126 HEADER_STRUCT.pack_into(data, 0, self.size, self.version)
127 position = HEADER_STRUCT.size
128 to_pack = []
129 for group in self._groups:
130 position = position + NeededPaddingForAlignment(position,
131 group.GetByteSize())
132 (entry, new_handles) = group.Serialize(
133 obj,
134 len(data) - position,
135 data,
136 handle_offset + len(handles))
137 to_pack.append(entry)
138 handles.extend(new_handles)
139 position = position + group.GetByteSize()
140 self._GetMainStruct().pack_into(data, HEADER_STRUCT.size, *to_pack)
141 return (data, handles)
142
143 def Deserialize(self, fields, context):
144 if len(context.data) < HEADER_STRUCT.size:
145 raise DeserializationException(
146 'Available data too short to contain header.')
147 (size, version) = HEADER_STRUCT.unpack_from(context.data)
148 if len(context.data) < size or size < HEADER_STRUCT.size:
149 raise DeserializationException('Header size is incorrect.')
150 if context.IsInitialContext():
151 context.ClaimMemory(0, size)
152 version_struct = self._GetStruct(version)
153 entitities = version_struct.unpack_from(context.data, HEADER_STRUCT.size)
154 filtered_groups = self._GetGroups(version)
155 position = HEADER_STRUCT.size
156 for (group, value) in zip(filtered_groups, entitities):
157 position = position + NeededPaddingForAlignment(position,
158 group.GetByteSize())
159 fields.update(group.Deserialize(value, context.GetSubContext(position)))
160 position += group.GetByteSize()
161
162
163 def NeededPaddingForAlignment(value, alignment=8):
164 """Returns the padding necessary to align value with the given alignment."""
165 if value % alignment:
166 return alignment - (value % alignment)
167 return 0
168
169
170 def _GetVersion(groups):
171 return sum([len(x.descriptors) for x in groups])
172
173
174 def _FilterGroups(groups, version):
175 return [group for group in groups if group.GetVersion() < version]
176
177
178 def _GetStruct(groups):
179 index = 0
180 codes = [ '<' ]
181 for group in groups:
182 code = group.GetTypeCode()
183 size = group.GetByteSize()
184 needed_padding = NeededPaddingForAlignment(index, size)
185 if needed_padding:
186 codes.append('x' * needed_padding)
187 index = index + needed_padding
188 codes.append(code)
189 index = index + size
190 alignment_needed = NeededPaddingForAlignment(index)
191 if alignment_needed:
192 codes.append('x' * alignment_needed)
193 return struct.Struct(''.join(codes))
OLDNEW
« no previous file with comments | « mojo/public/python/mojo_bindings/reflection.py ('k') | mojo/public/python/mojo_system.pyx » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698