1var Writable = require('readable-stream').Writable 2var inherits = require('inherits') 3var bufferFrom = require('buffer-from') 4 5if (typeof Uint8Array === 'undefined') { 6 var U8 = require('typedarray').Uint8Array 7} else { 8 var U8 = Uint8Array 9} 10 11function ConcatStream(opts, cb) { 12 if (!(this instanceof ConcatStream)) return new ConcatStream(opts, cb) 13 14 if (typeof opts === 'function') { 15 cb = opts 16 opts = {} 17 } 18 if (!opts) opts = {} 19 20 var encoding = opts.encoding 21 var shouldInferEncoding = false 22 23 if (!encoding) { 24 shouldInferEncoding = true 25 } else { 26 encoding = String(encoding).toLowerCase() 27 if (encoding === 'u8' || encoding === 'uint8') { 28 encoding = 'uint8array' 29 } 30 } 31 32 Writable.call(this, { objectMode: true }) 33 34 this.encoding = encoding 35 this.shouldInferEncoding = shouldInferEncoding 36 37 if (cb) this.on('finish', function () { cb(this.getBody()) }) 38 this.body = [] 39} 40 41module.exports = ConcatStream 42inherits(ConcatStream, Writable) 43 44ConcatStream.prototype._write = function(chunk, enc, next) { 45 this.body.push(chunk) 46 next() 47} 48 49ConcatStream.prototype.inferEncoding = function (buff) { 50 var firstBuffer = buff === undefined ? this.body[0] : buff; 51 if (Buffer.isBuffer(firstBuffer)) return 'buffer' 52 if (typeof Uint8Array !== 'undefined' && firstBuffer instanceof Uint8Array) return 'uint8array' 53 if (Array.isArray(firstBuffer)) return 'array' 54 if (typeof firstBuffer === 'string') return 'string' 55 if (Object.prototype.toString.call(firstBuffer) === "[object Object]") return 'object' 56 return 'buffer' 57} 58 59ConcatStream.prototype.getBody = function () { 60 if (!this.encoding && this.body.length === 0) return [] 61 if (this.shouldInferEncoding) this.encoding = this.inferEncoding() 62 if (this.encoding === 'array') return arrayConcat(this.body) 63 if (this.encoding === 'string') return stringConcat(this.body) 64 if (this.encoding === 'buffer') return bufferConcat(this.body) 65 if (this.encoding === 'uint8array') return u8Concat(this.body) 66 return this.body 67} 68 69var isArray = Array.isArray || function (arr) { 70 return Object.prototype.toString.call(arr) == '[object Array]' 71} 72 73function isArrayish (arr) { 74 return /Array\]$/.test(Object.prototype.toString.call(arr)) 75} 76 77function isBufferish (p) { 78 return typeof p === 'string' || isArrayish(p) || (p && typeof p.subarray === 'function') 79} 80 81function stringConcat (parts) { 82 var strings = [] 83 var needsToString = false 84 for (var i = 0; i < parts.length; i++) { 85 var p = parts[i] 86 if (typeof p === 'string') { 87 strings.push(p) 88 } else if (Buffer.isBuffer(p)) { 89 strings.push(p) 90 } else if (isBufferish(p)) { 91 strings.push(bufferFrom(p)) 92 } else { 93 strings.push(bufferFrom(String(p))) 94 } 95 } 96 if (Buffer.isBuffer(parts[0])) { 97 strings = Buffer.concat(strings) 98 strings = strings.toString('utf8') 99 } else { 100 strings = strings.join('') 101 } 102 return strings 103} 104 105function bufferConcat (parts) { 106 var bufs = [] 107 for (var i = 0; i < parts.length; i++) { 108 var p = parts[i] 109 if (Buffer.isBuffer(p)) { 110 bufs.push(p) 111 } else if (isBufferish(p)) { 112 bufs.push(bufferFrom(p)) 113 } else { 114 bufs.push(bufferFrom(String(p))) 115 } 116 } 117 return Buffer.concat(bufs) 118} 119 120function arrayConcat (parts) { 121 var res = [] 122 for (var i = 0; i < parts.length; i++) { 123 res.push.apply(res, parts[i]) 124 } 125 return res 126} 127 128function u8Concat (parts) { 129 var len = 0 130 for (var i = 0; i < parts.length; i++) { 131 if (typeof parts[i] === 'string') { 132 parts[i] = bufferFrom(parts[i]) 133 } 134 len += parts[i].length 135 } 136 var u8 = new U8(len) 137 for (var i = 0, offset = 0; i < parts.length; i++) { 138 var part = parts[i] 139 for (var j = 0; j < part.length; j++) { 140 u8[offset++] = part[j] 141 } 142 } 143 return u8 144} 145