buffer-util.js (3044B)
1 'use strict'; 2 3 const { EMPTY_BUFFER } = require('./constants'); 4 5 /** 6 * Merges an array of buffers into a new buffer. 7 * 8 * @param {Buffer[]} list The array of buffers to concat 9 * @param {Number} totalLength The total length of buffers in the list 10 * @return {Buffer} The resulting buffer 11 * @public 12 */ 13 function concat(list, totalLength) { 14 if (list.length === 0) return EMPTY_BUFFER; 15 if (list.length === 1) return list[0]; 16 17 const target = Buffer.allocUnsafe(totalLength); 18 let offset = 0; 19 20 for (let i = 0; i < list.length; i++) { 21 const buf = list[i]; 22 target.set(buf, offset); 23 offset += buf.length; 24 } 25 26 if (offset < totalLength) return target.slice(0, offset); 27 28 return target; 29 } 30 31 /** 32 * Masks a buffer using the given mask. 33 * 34 * @param {Buffer} source The buffer to mask 35 * @param {Buffer} mask The mask to use 36 * @param {Buffer} output The buffer where to store the result 37 * @param {Number} offset The offset at which to start writing 38 * @param {Number} length The number of bytes to mask. 39 * @public 40 */ 41 function _mask(source, mask, output, offset, length) { 42 for (let i = 0; i < length; i++) { 43 output[offset + i] = source[i] ^ mask[i & 3]; 44 } 45 } 46 47 /** 48 * Unmasks a buffer using the given mask. 49 * 50 * @param {Buffer} buffer The buffer to unmask 51 * @param {Buffer} mask The mask to use 52 * @public 53 */ 54 function _unmask(buffer, mask) { 55 // Required until https://github.com/nodejs/node/issues/9006 is resolved. 56 const length = buffer.length; 57 for (let i = 0; i < length; i++) { 58 buffer[i] ^= mask[i & 3]; 59 } 60 } 61 62 /** 63 * Converts a buffer to an `ArrayBuffer`. 64 * 65 * @param {Buffer} buf The buffer to convert 66 * @return {ArrayBuffer} Converted buffer 67 * @public 68 */ 69 function toArrayBuffer(buf) { 70 if (buf.byteLength === buf.buffer.byteLength) { 71 return buf.buffer; 72 } 73 74 return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); 75 } 76 77 /** 78 * Converts `data` to a `Buffer`. 79 * 80 * @param {*} data The data to convert 81 * @return {Buffer} The buffer 82 * @throws {TypeError} 83 * @public 84 */ 85 function toBuffer(data) { 86 toBuffer.readOnly = true; 87 88 if (Buffer.isBuffer(data)) return data; 89 90 let buf; 91 92 if (data instanceof ArrayBuffer) { 93 buf = Buffer.from(data); 94 } else if (ArrayBuffer.isView(data)) { 95 buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength); 96 } else { 97 buf = Buffer.from(data); 98 toBuffer.readOnly = false; 99 } 100 101 return buf; 102 } 103 104 try { 105 const bufferUtil = require('bufferutil'); 106 const bu = bufferUtil.BufferUtil || bufferUtil; 107 108 module.exports = { 109 concat, 110 mask(source, mask, output, offset, length) { 111 if (length < 48) _mask(source, mask, output, offset, length); 112 else bu.mask(source, mask, output, offset, length); 113 }, 114 toArrayBuffer, 115 toBuffer, 116 unmask(buffer, mask) { 117 if (buffer.length < 32) _unmask(buffer, mask); 118 else bu.unmask(buffer, mask); 119 } 120 }; 121 } catch (e) /* istanbul ignore next */ { 122 module.exports = { 123 concat, 124 mask: _mask, 125 toArrayBuffer, 126 toBuffer, 127 unmask: _unmask 128 }; 129 }