index.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. const { Transform } = require('readable-stream')
  2. class Block extends Transform {
  3. constructor (size, opts = {}) {
  4. super(opts)
  5. if (typeof size === 'object') {
  6. opts = size
  7. size = opts.size
  8. }
  9. this.size = size || 512
  10. const { nopad, zeroPadding = true } = opts
  11. if (nopad) this._zeroPadding = false
  12. else this._zeroPadding = !!zeroPadding
  13. this._buffered = []
  14. this._bufferedBytes = 0
  15. }
  16. _transform (buf, enc, next) {
  17. this._bufferedBytes += buf.length
  18. this._buffered.push(buf)
  19. while (this._bufferedBytes >= this.size) {
  20. this._bufferedBytes -= this.size
  21. // Assemble the buffers that will compose the final block
  22. const blockBufs = []
  23. let blockBufsBytes = 0
  24. while (blockBufsBytes < this.size) {
  25. const b = this._buffered.shift()
  26. if (blockBufsBytes + b.length <= this.size) {
  27. blockBufs.push(b)
  28. blockBufsBytes += b.length
  29. } else {
  30. // If the last buffer is larger than needed for the block, just
  31. // use the needed part
  32. const neededSize = this.size - blockBufsBytes
  33. blockBufs.push(b.slice(0, neededSize))
  34. blockBufsBytes += neededSize
  35. this._buffered.unshift(b.slice(neededSize))
  36. }
  37. }
  38. // Then concat just those buffers, leaving the rest untouched in _buffered
  39. this.push(Buffer.concat(blockBufs, this.size))
  40. }
  41. next()
  42. }
  43. _flush () {
  44. if (this._bufferedBytes && this._zeroPadding) {
  45. const zeroes = Buffer.alloc(this.size - this._bufferedBytes)
  46. this._buffered.push(zeroes)
  47. this.push(Buffer.concat(this._buffered))
  48. this._buffered = null
  49. } else if (this._bufferedBytes) {
  50. this.push(Buffer.concat(this._buffered))
  51. this._buffered = null
  52. }
  53. this.push(null)
  54. }
  55. }
  56. module.exports = Block