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

Unified Diff: mojo/python/mojo_utils/data_pipe_utils.py

Issue 952223002: Add Python util to read from a data pipe into a bytearray (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Move to AsyncWait, add tests Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
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)

Powered by Google App Engine
This is Rietveld 408576698