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 == mojo_system.DEADLINE_INDEFINITE: |
| 38 return self.original_deadline |
| 39 elapsed_time = mojo_system.GetTimeTicksNow() - self.start_time |
| 40 return max(0, self.original_deadline - elapsed_time) |
| 41 |
| 42 def CopyFromDataPipeAsync(self, result): |
| 43 while result == mojo_system.RESULT_OK: |
| 44 assert self.index <= len(self.data) |
| 45 if self.index == len(self.data): |
| 46 self.buffer_size *= 2 |
| 47 self.data.extend(itertools.repeat(0, self.buffer_size)) |
| 48 |
| 49 # Careful! Have to construct a memoryview object here as otherwise the |
| 50 # slice operation will create a copy of |data| and hence not write into |
| 51 # |data| as desired. |
| 52 result, read_bytes = self.data_pipe.ReadData( |
| 53 memoryview(self.data)[self.index:]) |
| 54 if read_bytes: |
| 55 self.index += len(read_bytes) |
| 56 del read_bytes |
| 57 |
| 58 if result == mojo_system.RESULT_SHOULD_WAIT: |
| 59 data_pipe.AsyncWait(mojo_system.HANDLE_SIGNAL_READABLE, |
| 60 self._ComputeCurrentDeadline(), |
| 61 self.CopyFromDataPipeAsync) |
| 62 return |
| 63 |
| 64 # Treat a failed precondition as EOF. |
| 65 if result == mojo_system.RESULT_FAILED_PRECONDITION: |
| 66 self.resolve(self.data[:self.index]) |
| 67 return |
| 68 |
| 69 self.reject(DataPipeCopyException("Result: %d" % result)) |
| 70 |
| 71 |
| 72 def GenerationMethod(resolve, reject): |
| 73 helper = DataPipeCopyHelper(data_pipe, deadline, resolve, reject) |
| 74 helper.CopyFromDataPipeAsync(mojo_system.RESULT_OK) |
| 75 |
| 76 return promise.Promise(GenerationMethod) |
OLD | NEW |