Index: mojo/python/mojo_utils/data_pipe_utils.py |
diff --git a/mojo/python/mojo_utils/data_pipe_utils.py b/mojo/python/mojo_utils/data_pipe_utils.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4299edb76e9391bfa1f2ec4f7752ca330a7a3082 |
--- /dev/null |
+++ b/mojo/python/mojo_utils/data_pipe_utils.py |
@@ -0,0 +1,77 @@ |
+# Copyright 2015 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+import itertools |
+import sys |
+ |
+import mojo_system |
+from mojo_bindings import promise |
+ |
+class DataPipeCopyException(Exception): |
+ def __init__(self, *args, **kwargs): |
+ Exception.__init__(self, *args, **kwargs) |
+ self.__traceback__ = sys.exc_info()[2] |
+ |
+ |
+def CopyFromDataPipe(data_pipe, deadline): |
+ """ |
+ Returns a Promise that operates as follows: |
+ - If |data_pipe| is successfully read from, the promise resolves with the |
+ bytes that were read. |
+ - Otherwise, the promise rejects with an exception whose message contains the |
+ status from the attempted read. |
+ """ |
+ class DataPipeCopyHelper(): |
+ def __init__(self, data_pipe, deadline, resolve, reject): |
+ self.data_pipe = data_pipe |
+ self.original_deadline = deadline |
+ self.start_time = mojo_system.GetTimeTicksNow() |
+ self.resolve = resolve |
+ self.reject = reject |
+ self.buffer_size = 1024 |
+ self.data = bytearray(self.buffer_size) |
+ self.index = 0 |
+ |
+ def _ComputeCurrentDeadline(self): |
+ if (self.original_deadline == 0 or |
+ self.original_deadline == mojo_system.DEADLINE_INDEFINITE): |
+ return self.original_deadline |
+ elapsed_time = mojo_system.GetTimeTicksNow() - self.start_time |
+ 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.
|
+ |
+ def CopyFromDataPipeAsync(self, result): |
+ while result == mojo_system.RESULT_OK: |
+ assert self.index <= len(self.data) |
+ if self.index == len(self.data): |
+ self.buffer_size *= 2 |
+ self.data.extend(itertools.repeat(0, self.buffer_size)) |
+ |
+ # Careful! Have to construct a memoryview object here as otherwise the |
+ # slice operation will create a copy of |data| and hence not write into |
+ # |data| as desired. |
+ result, read_bytes = self.data_pipe.ReadData( |
+ memoryview(self.data)[self.index:]) |
+ if read_bytes: |
+ self.index += len(read_bytes) |
+ del read_bytes |
+ |
+ if result == mojo_system.RESULT_SHOULD_WAIT: |
+ data_pipe.AsyncWait(mojo_system.HANDLE_SIGNAL_READABLE, |
+ self._ComputeCurrentDeadline(), |
+ self.CopyFromDataPipeAsync) |
+ return |
+ |
+ # Treat a failed precondition as EOF. |
+ if result == mojo_system.RESULT_FAILED_PRECONDITION: |
+ self.resolve(self.data[:self.index]) |
+ return |
+ |
+ self.reject(DataPipeCopyException("Result: %d" % result)) |
+ |
+ |
+ def GenerationMethod(resolve, reject): |
+ helper = DataPipeCopyHelper(data_pipe, deadline, resolve, reject) |
+ helper.CopyFromDataPipeAsync(mojo_system.RESULT_OK) |
+ |
+ return promise.Promise(GenerationMethod) |