• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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