text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.transduce = transduce;
  
  var _Stream = require('../Stream');
  
  var _Stream2 = _interopRequireDefault(_Stream);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * Transform a stream by passing its events through a transducer.
   * @param  {function} transducer transducer function
   * @param  {Stream} stream stream whose events will be passed through the
   *  transducer
   * @return {Stream} stream of events transformed by the transducer
   */
  function transduce(transducer, stream) {
    return new _Stream2.default(new Transduce(transducer, stream.source));
  } /** @license MIT License (c) copyright 2010-2016 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  function Transduce(transducer, source) {
    this.transducer = transducer;
    this.source = source;
  }
  
  Transduce.prototype.run = function (sink, scheduler) {
    var xf = this.transducer(new Transformer(sink));
    return this.source.run(new TransduceSink(getTxHandler(xf), sink), scheduler);
  };
  
  function TransduceSink(adapter, sink) {
    this.xf = adapter;
    this.sink = sink;
  }
  
  TransduceSink.prototype.event = function (t, x) {
    var next = this.xf.step(t, x);
  
    return this.xf.isReduced(next) ? this.sink.end(t, this.xf.getResult(next)) : next;
  };
  
  TransduceSink.prototype.end = function (t, x) {
    return this.xf.result(x);
  };
  
  TransduceSink.prototype.error = function (t, e) {
    return this.sink.error(t, e);
  };
  
  function Transformer(sink) {
    this.time = -Infinity;
    this.sink = sink;
  }
  
  Transformer.prototype['@@transducer/init'] = Transformer.prototype.init = function () {};
  
  Transformer.prototype['@@transducer/step'] = Transformer.prototype.step = function (t, x) {
    if (!isNaN(t)) {
      this.time = Math.max(t, this.time);
    }
    return this.sink.event(this.time, x);
  };
  
  Transformer.prototype['@@transducer/result'] = Transformer.prototype.result = function (x) {
    return this.sink.end(this.time, x);
  };
  
  /**
  * Given an object supporting the new or legacy transducer protocol,
  * create an adapter for it.
  * @param {object} tx transform
  * @returns {TxAdapter|LegacyTxAdapter}
  */
  function getTxHandler(tx) {
    return typeof tx['@@transducer/step'] === 'function' ? new TxAdapter(tx) : new LegacyTxAdapter(tx);
  }
  
  /**
  * Adapter for new official transducer protocol
  * @param {object} tx transform
  * @constructor
  */
  function TxAdapter(tx) {
    this.tx = tx;
  }
  
  TxAdapter.prototype.step = function (t, x) {
    return this.tx['@@transducer/step'](t, x);
  };
  TxAdapter.prototype.result = function (x) {
    return this.tx['@@transducer/result'](x);
  };
  TxAdapter.prototype.isReduced = function (x) {
    return x != null && x['@@transducer/reduced'];
  };
  TxAdapter.prototype.getResult = function (x) {
    return x['@@transducer/value'];
  };
  
  /**
  * Adapter for older transducer protocol
  * @param {object} tx transform
  * @constructor
  */
  function LegacyTxAdapter(tx) {
    this.tx = tx;
  }
  
  LegacyTxAdapter.prototype.step = function (t, x) {
    return this.tx.step(t, x);
  };
  LegacyTxAdapter.prototype.result = function (x) {
    return this.tx.result(x);
  };
  LegacyTxAdapter.prototype.isReduced = function (x) {
    return x != null && x.__transducers_reduced__;
  };
  LegacyTxAdapter.prototype.getResult = function (x) {
    return x.value;
  };