text: /* */ 
  
  var keys = exports.keys =
  function (object) {
    return values(Object.keys(object))
  }
  
  var once = exports.once =
  function (value) {
    return function (abort, cb) {
      if(abort) return cb(abort)
      if(value != null) {
        var _value = value; value = null
        cb(null, _value)
      } else
        cb(true)
    }
  }
  
  var values = exports.values = exports.readArray =
  function (array) {
    if(!Array.isArray(array))
      array = Object.keys(array).map(function (k) {
        return array[k]
      })
    var i = 0
    return function (end, cb) {
      if(end)
        return cb && cb(end)  
      cb(i >= array.length || null, array[i++])
    }
  }
  
  
  var count = exports.count = 
  function (max) {
    var i = 0; max = max || Infinity
    return function (end, cb) {
      if(end) return cb && cb(end)
      if(i > max)
        return cb(true)
      cb(null, i++)
    }
  }
  
  var infinite = exports.infinite = 
  function (generate) {
    generate = generate || Math.random
    return function (end, cb) {
      if(end) return cb && cb(end)
      return cb(null, generate())
    }
  }
  
  var defer = exports.defer = function () {
    var _read, cbs = [], _end
  
    var read = function (end, cb) {
      if(!_read) {
        _end = end
        cbs.push(cb)
      } 
      else _read(end, cb)
    }
    read.resolve = function (read) {
      if(_read) throw new Error('already resolved')
      _read = read
      if(!_read) throw new Error('no read cannot resolve!' + _read)
      while(cbs.length)
        _read(_end, cbs.shift())
    }
    read.abort = function(err) {
      read.resolve(function (_, cb) {
        cb(err || true)
      })
    }
    return read
  }
  
  var empty = exports.empty = function () {
    return function (abort, cb) {
      cb(true)
    }
  }
  
  var depthFirst = exports.depthFirst =
  function (start, createStream) {
    var reads = []
  
    reads.unshift(once(start))
  
    return function next (end, cb) {
      if(!reads.length)
        return cb(true)
      reads[0](end, function (end, data) {
        if(end) {
          //if this stream has ended, go to the next queue
          reads.shift()
          return next(null, cb)
        }
        reads.unshift(createStream(data))
        cb(end, data)
      })
    }
  }
  //width first is just like depth first,
  //but push each new stream onto the end of the queue
  var widthFirst = exports.widthFirst = 
  function (start, createStream) {
    var reads = []
  
    reads.push(once(start))
  
    return function next (end, cb) {
      if(!reads.length)
        return cb(true)
      reads[0](end, function (end, data) {
        if(end) {
          reads.shift()
          return next(null, cb)
        }
        reads.push(createStream(data))
        cb(end, data)
      })
    }
  }
  
  //this came out different to the first (strm)
  //attempt at leafFirst, but it's still a valid
  //topological sort.
  var leafFirst = exports.leafFirst = 
  function (start, createStream) {
    var reads = []
    var output = []
    reads.push(once(start))
    
    return function next (end, cb) {
      reads[0](end, function (end, data) {
        if(end) {
          reads.shift()
          if(!output.length)
            return cb(true)
          return cb(null, output.shift())
        }
        reads.unshift(createStream(data))
        output.unshift(data)
        next(null, cb)
      })
    }
  }
  
  