OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2015 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 import itertools | |
6 import sys | |
7 | |
8 import mojo_system | |
9 from mojo_bindings import promise | |
10 | |
11 class DataPipeCopyException(Exception): | |
12 def __init__(self, *args, **kwargs): | |
13 Exception.__init__(self, *args, **kwargs) | |
14 self.__traceback__ = sys.exc_info()[2] | |
15 | |
16 | |
17 def CopyFromDataPipe(data_pipe, deadline): | |
18 """ | |
19 Returns a Promise that operates as follows: | |
20 - If |data_pipe| is successfully read from, the promise resolves with the | |
21 bytes that were read. | |
22 - Otherwise, the promise rejects with an exception whose message contains the | |
23 status from the attempted read. | |
24 """ | |
25 class DataPipeCopyHelper(): | |
26 def __init__(self, data_pipe, deadline, resolve, reject): | |
27 self.data_pipe = data_pipe | |
28 self.original_deadline = deadline | |
29 self.start_time = mojo_system.GetTimeTicksNow() | |
30 self.resolve = resolve | |
31 self.reject = reject | |
32 self.buffer_size = 1024 | |
33 self.data = bytearray(self.buffer_size) | |
34 self.index = 0 | |
35 | |
36 def _ComputeCurrentDeadline(self): | |
37 if (self.original_deadline == 0 or | |
38 self.original_deadline == mojo_system.DEADLINE_INDEFINITE): | |
39 return self.original_deadline | |
40 elapsed_time = mojo_system.GetTimeTicksNow() - self.start_time | |
41 return self.original_deadline - elapsed_time | |
qsr
2015/03/03 17:10:36
You probably want a max(0, self.original_deadline
blundell
2015/03/04 10:28:52
Done.
| |
42 | |
43 def CopyFromDataPipeAsync(self, result): | |
44 while result == mojo_system.RESULT_OK: | |
45 assert self.index <= len(self.data) | |
46 if self.index == len(self.data): | |
47 self.buffer_size *= 2 | |
48 self.data.extend(itertools.repeat(0, self.buffer_size)) | |
49 | |
50 # Careful! Have to construct a memoryview object here as otherwise the | |
51 # slice operation will create a copy of |data| and hence not write into | |
52 # |data| as desired. | |
53 result, read_bytes = self.data_pipe.ReadData( | |
54 memoryview(self.data)[self.index:]) | |
55 if read_bytes: | |
56 self.index += len(read_bytes) | |
57 del read_bytes | |
58 | |
59 if result == mojo_system.RESULT_SHOULD_WAIT: | |
60 data_pipe.AsyncWait(mojo_system.HANDLE_SIGNAL_READABLE, | |
61 self._ComputeCurrentDeadline(), | |
62 self.CopyFromDataPipeAsync) | |
63 return | |
64 | |
65 # Treat a failed precondition as EOF. | |
66 if result == mojo_system.RESULT_FAILED_PRECONDITION: | |
67 self.resolve(self.data[:self.index]) | |
68 return | |
69 | |
70 self.reject(DataPipeCopyException("Result: %d" % result)) | |
71 | |
72 | |
73 def GenerationMethod(resolve, reject): | |
74 helper = DataPipeCopyHelper(data_pipe, deadline, resolve, reject) | |
75 helper.CopyFromDataPipeAsync(mojo_system.RESULT_OK) | |
76 | |
77 return promise.Promise(GenerationMethod) | |
OLD | NEW |