buffer-util.js (2971B)
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 for (let i = 0; i < buffer.length; i++) { 56 buffer[i] ^= mask[i & 3]; 57 } 58 } 59 60 /** 61 * Converts a buffer to an `ArrayBuffer`. 62 * 63 * @param {Buffer} buf The buffer to convert 64 * @return {ArrayBuffer} Converted buffer 65 * @public 66 */ 67 function toArrayBuffer(buf) { 68 if (buf.byteLength === buf.buffer.byteLength) { 69 return buf.buffer; 70 } 71 72 return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); 73 } 74 75 /** 76 * Converts `data` to a `Buffer`. 77 * 78 * @param {*} data The data to convert 79 * @return {Buffer} The buffer 80 * @throws {TypeError} 81 * @public 82 */ 83 function toBuffer(data) { 84 toBuffer.readOnly = true; 85 86 if (Buffer.isBuffer(data)) return data; 87 88 let buf; 89 90 if (data instanceof ArrayBuffer) { 91 buf = Buffer.from(data); 92 } else if (ArrayBuffer.isView(data)) { 93 buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength); 94 } else { 95 buf = Buffer.from(data); 96 toBuffer.readOnly = false; 97 } 98 99 return buf; 100 } 101 102 module.exports = { 103 concat, 104 mask: _mask, 105 toArrayBuffer, 106 toBuffer, 107 unmask: _unmask 108 }; 109 110 /* istanbul ignore else */ 111 if (!process.env.WS_NO_BUFFER_UTIL) { 112 try { 113 const bufferUtil = require('bufferutil'); 114 115 module.exports.mask = function (source, mask, output, offset, length) { 116 if (length < 48) _mask(source, mask, output, offset, length); 117 else bufferUtil.mask(source, mask, output, offset, length); 118 }; 119 120 module.exports.unmask = function (buffer, mask) { 121 if (buffer.length < 32) _unmask(buffer, mask); 122 else bufferUtil.unmask(buffer, mask); 123 }; 124 } catch (e) { 125 // Continue regardless of the error. 126 } 127 }