127 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			127 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 'use strict'; | ||
|  | 
 | ||
|  | const { EMPTY_BUFFER } = require('./constants'); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Merges an array of buffers into a new buffer. | ||
|  |  * | ||
|  |  * @param {Buffer[]} list The array of buffers to concat | ||
|  |  * @param {Number} totalLength The total length of buffers in the list | ||
|  |  * @return {Buffer} The resulting buffer | ||
|  |  * @public | ||
|  |  */ | ||
|  | function concat(list, totalLength) { | ||
|  |   if (list.length === 0) return EMPTY_BUFFER; | ||
|  |   if (list.length === 1) return list[0]; | ||
|  | 
 | ||
|  |   const target = Buffer.allocUnsafe(totalLength); | ||
|  |   let offset = 0; | ||
|  | 
 | ||
|  |   for (let i = 0; i < list.length; i++) { | ||
|  |     const buf = list[i]; | ||
|  |     target.set(buf, offset); | ||
|  |     offset += buf.length; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (offset < totalLength) return target.slice(0, offset); | ||
|  | 
 | ||
|  |   return target; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Masks a buffer using the given mask. | ||
|  |  * | ||
|  |  * @param {Buffer} source The buffer to mask | ||
|  |  * @param {Buffer} mask The mask to use | ||
|  |  * @param {Buffer} output The buffer where to store the result | ||
|  |  * @param {Number} offset The offset at which to start writing | ||
|  |  * @param {Number} length The number of bytes to mask. | ||
|  |  * @public | ||
|  |  */ | ||
|  | function _mask(source, mask, output, offset, length) { | ||
|  |   for (let i = 0; i < length; i++) { | ||
|  |     output[offset + i] = source[i] ^ mask[i & 3]; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Unmasks a buffer using the given mask. | ||
|  |  * | ||
|  |  * @param {Buffer} buffer The buffer to unmask | ||
|  |  * @param {Buffer} mask The mask to use | ||
|  |  * @public | ||
|  |  */ | ||
|  | function _unmask(buffer, mask) { | ||
|  |   for (let i = 0; i < buffer.length; i++) { | ||
|  |     buffer[i] ^= mask[i & 3]; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Converts a buffer to an `ArrayBuffer`. | ||
|  |  * | ||
|  |  * @param {Buffer} buf The buffer to convert | ||
|  |  * @return {ArrayBuffer} Converted buffer | ||
|  |  * @public | ||
|  |  */ | ||
|  | function toArrayBuffer(buf) { | ||
|  |   if (buf.byteLength === buf.buffer.byteLength) { | ||
|  |     return buf.buffer; | ||
|  |   } | ||
|  | 
 | ||
|  |   return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Converts `data` to a `Buffer`. | ||
|  |  * | ||
|  |  * @param {*} data The data to convert | ||
|  |  * @return {Buffer} The buffer | ||
|  |  * @throws {TypeError} | ||
|  |  * @public | ||
|  |  */ | ||
|  | function toBuffer(data) { | ||
|  |   toBuffer.readOnly = true; | ||
|  | 
 | ||
|  |   if (Buffer.isBuffer(data)) return data; | ||
|  | 
 | ||
|  |   let buf; | ||
|  | 
 | ||
|  |   if (data instanceof ArrayBuffer) { | ||
|  |     buf = Buffer.from(data); | ||
|  |   } else if (ArrayBuffer.isView(data)) { | ||
|  |     buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength); | ||
|  |   } else { | ||
|  |     buf = Buffer.from(data); | ||
|  |     toBuffer.readOnly = false; | ||
|  |   } | ||
|  | 
 | ||
|  |   return buf; | ||
|  | } | ||
|  | 
 | ||
|  | try { | ||
|  |   const bufferUtil = require('bufferutil'); | ||
|  | 
 | ||
|  |   module.exports = { | ||
|  |     concat, | ||
|  |     mask(source, mask, output, offset, length) { | ||
|  |       if (length < 48) _mask(source, mask, output, offset, length); | ||
|  |       else bufferUtil.mask(source, mask, output, offset, length); | ||
|  |     }, | ||
|  |     toArrayBuffer, | ||
|  |     toBuffer, | ||
|  |     unmask(buffer, mask) { | ||
|  |       if (buffer.length < 32) _unmask(buffer, mask); | ||
|  |       else bufferUtil.unmask(buffer, mask); | ||
|  |     } | ||
|  |   }; | ||
|  | } catch (e) /* istanbul ignore next */ { | ||
|  |   module.exports = { | ||
|  |     concat, | ||
|  |     mask: _mask, | ||
|  |     toArrayBuffer, | ||
|  |     toBuffer, | ||
|  |     unmask: _unmask | ||
|  |   }; | ||
|  | } |