| // 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 'dart:async'; |
| import 'dart:io'; |
| import 'dart:typed_data'; |
| |
| import 'package:mojo/core.dart'; |
| |
| // Helper class to drain the contents of a mojo data pipe to a file. |
| class PipeToFile { |
| MojoDataPipeConsumer _consumer; |
| MojoEventStream _eventStream; |
| IOSink _outputStream; |
| |
| PipeToFile(this._consumer, String outputPath) { |
| _eventStream = new MojoEventStream(_consumer.handle); |
| _outputStream = new File(outputPath).openWrite(); |
| } |
| |
| Future<MojoResult> _doRead() async { |
| ByteData thisRead = _consumer.beginRead(); |
| if (thisRead == null) { |
| throw 'Data pipe beginRead failed: ${_consumer.status}'; |
| } |
| // TODO(mpcomplete): Should I worry about the _eventStream listen callback |
| // being invoked again before this completes? |
| await _outputStream.add(thisRead.buffer.asUint8List()); |
| return _consumer.endRead(thisRead.lengthInBytes); |
| } |
| |
| Future drain() async { |
| Completer completer = new Completer(); |
| // TODO(mpcomplete): Is it legit to pass an async callback to listen? |
| _eventStream.listen((List<int> event) async { |
| MojoHandleSignals mojoSignals = new MojoHandleSignals(event[1]); |
| if (mojoSignals.isReadable) { |
| MojoResult result = await _doRead(); |
| if (!result.isOk) { |
| _eventStream.close(); |
| _eventStream = null; |
| _outputStream.close(); |
| completer.complete(result); |
| } else { |
| _eventStream.enableReadEvents(); |
| } |
| } else if (mojoSignals.isPeerClosed) { |
| _eventStream.close(); |
| _eventStream = null; |
| _outputStream.close(); |
| completer.complete(MojoResult.OK); |
| } else { |
| throw 'Unexpected handle event: $mojoSignals'; |
| } |
| }); |
| return completer.future; |
| } |
| |
| static Future<MojoResult> copyToFile(MojoDataPipeConsumer consumer, String outputPath) { |
| PipeToFile drainer = new PipeToFile(consumer, outputPath); |
| return drainer.drain(); |
| } |
| } |