index.js 3.7 KB

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