buffer-util.js (3389B)
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 = viewToBuffer(data); 96 } else { 97 buf = Buffer.from(data); 98 toBuffer.readOnly = false; 99 } 100 101 return buf; 102 } 103 104 /** 105 * Converts an `ArrayBuffer` view into a buffer. 106 * 107 * @param {(DataView|TypedArray)} view The view to convert 108 * @return {Buffer} Converted view 109 * @private 110 */ 111 function viewToBuffer(view) { 112 const buf = Buffer.from(view.buffer); 113 114 if (view.byteLength !== view.buffer.byteLength) { 115 return buf.slice(view.byteOffset, view.byteOffset + view.byteLength); 116 } 117 118 return buf; 119 } 120 121 try { 122 const bufferUtil = require('bufferutil'); 123 const bu = bufferUtil.BufferUtil || bufferUtil; 124 125 module.exports = { 126 concat, 127 mask(source, mask, output, offset, length) { 128 if (length < 48) _mask(source, mask, output, offset, length); 129 else bu.mask(source, mask, output, offset, length); 130 }, 131 toArrayBuffer, 132 toBuffer, 133 unmask(buffer, mask) { 134 if (buffer.length < 32) _unmask(buffer, mask); 135 else bu.unmask(buffer, mask); 136 } 137 }; 138 } catch (e) /* istanbul ignore next */ { 139 module.exports = { 140 concat, 141 mask: _mask, 142 toArrayBuffer, 143 toBuffer, 144 unmask: _unmask 145 }; 146 }