| 'use strict'; |
| const from = require('from2'); |
| const pIsPromise = require('p-is-promise'); |
| |
| module.exports = x => { |
| if (Array.isArray(x)) { |
| x = x.slice(); |
| } |
| |
| let promise; |
| let iterator; |
| |
| prepare(x); |
| |
| function prepare(value) { |
| x = value; |
| promise = pIsPromise(x) ? x : null; |
| // we don't iterate on strings and buffers since slicing them is ~7x faster |
| const shouldIterate = !promise && x[Symbol.iterator] && typeof x !== 'string' && !Buffer.isBuffer(x); |
| iterator = shouldIterate ? x[Symbol.iterator]() : null; |
| } |
| |
| return from(function reader(size, cb) { |
| if (promise) { |
| promise.then(prepare).then(() => reader.call(this, size, cb), cb); |
| return; |
| } |
| |
| if (iterator) { |
| const obj = iterator.next(); |
| setImmediate(cb, null, obj.done ? null : obj.value); |
| return; |
| } |
| |
| if (x.length === 0) { |
| setImmediate(cb, null, null); |
| return; |
| } |
| |
| const chunk = x.slice(0, size); |
| x = x.slice(size); |
| |
| setImmediate(cb, null, chunk); |
| }); |
| }; |
| |
| module.exports.obj = x => { |
| if (Array.isArray(x)) { |
| x = x.slice(); |
| } |
| |
| let promise; |
| let iterator; |
| |
| prepare(x); |
| |
| function prepare(value) { |
| x = value; |
| promise = pIsPromise(x) ? x : null; |
| iterator = !promise && x[Symbol.iterator] ? x[Symbol.iterator]() : null; |
| } |
| |
| return from.obj(function reader(size, cb) { |
| if (promise) { |
| promise.then(prepare).then(() => reader.call(this, size, cb), cb); |
| return; |
| } |
| |
| if (iterator) { |
| const obj = iterator.next(); |
| setImmediate(cb, null, obj.done ? null : obj.value); |
| return; |
| } |
| |
| this.push(x); |
| |
| setImmediate(cb, null, null); |
| }); |
| }; |