pipe_to_file.dart 1.99 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// 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;
Adam Barth's avatar
Adam Barth committed
14
  MojoEventSubscription _events;
15 16 17
  IOSink _outputStream;

  PipeToFile(this._consumer, String outputPath) {
Adam Barth's avatar
Adam Barth committed
18
    _events = new MojoEventSubscription(_consumer.handle);
19 20 21
    _outputStream = new File(outputPath).openWrite();
  }

Adam Barth's avatar
Adam Barth committed
22
  Future<int> _doRead() async {
23 24 25 26 27 28 29 30 31 32
    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);
  }

Adam Barth's avatar
Adam Barth committed
33 34
  Future<int> drain() {
    Completer<int> completer = new Completer();
Ian Hickson's avatar
Ian Hickson committed
35 36 37 38 39 40 41 42 43 44 45 46 47
    _events.subscribe((int signal) {
      (() async {
        if (MojoHandleSignals.isReadable(signal)) {
          int result = await _doRead();
          if (result != MojoResult.kOk) {
            _events.close();
            _events = null;
            _outputStream.close();
            completer.complete(result);
          } else {
            _events.enableReadEvents();
          }
        } else if (MojoHandleSignals.isPeerClosed(signal)) {
Adam Barth's avatar
Adam Barth committed
48 49
          _events.close();
          _events = null;
50
          _outputStream.close();
Ian Hickson's avatar
Ian Hickson committed
51
          completer.complete(MojoResult.kOk);
52
        } else {
Ian Hickson's avatar
Ian Hickson committed
53
          throw 'Unexpected handle event: ${MojoHandleSignals.string(signal)}';
54
        }
Ian Hickson's avatar
Ian Hickson committed
55
      })();
56 57 58 59
    });
    return completer.future;
  }

Adam Barth's avatar
Adam Barth committed
60
  static Future<int> copyToFile(MojoDataPipeConsumer consumer, String outputPath) {
61
    PipeToFile drainer = new PipeToFile(consumer, outputPath);
62 63 64
    return drainer.drain();
  }
}