forked from LittleChest/dns-packet
205 lines
4.9 KiB
JavaScript
205 lines
4.9 KiB
JavaScript
'use strict'
|
|
|
|
// Allocate a new Uint8Array buffer
|
|
function allocBuffer (size) {
|
|
return new Uint8Array(size)
|
|
}
|
|
|
|
// Allocate an uninitialized Uint8Array (same as allocBuffer for Uint8Array)
|
|
function allocUnsafeBuffer (size) {
|
|
return new Uint8Array(size)
|
|
}
|
|
|
|
// Check if an object is a Uint8Array
|
|
function isBuffer (obj) {
|
|
return obj instanceof Uint8Array
|
|
}
|
|
|
|
// Create Uint8Array from data with optional encoding
|
|
function fromBuffer (data, encoding) {
|
|
if (data instanceof Uint8Array) {
|
|
return new Uint8Array(data)
|
|
}
|
|
if (Array.isArray(data)) {
|
|
return new Uint8Array(data)
|
|
}
|
|
if (typeof data === 'string') {
|
|
if (encoding === 'base64') {
|
|
return base64ToBuffer(data)
|
|
} else if (encoding === 'hex') {
|
|
return hexToBuffer(data)
|
|
} else {
|
|
return stringToBuffer(data)
|
|
}
|
|
}
|
|
return new Uint8Array(data)
|
|
}
|
|
|
|
// Convert string to Uint8Array (UTF-8 encoding)
|
|
function stringToBuffer (str) {
|
|
const encoder = new TextEncoder()
|
|
return encoder.encode(str)
|
|
}
|
|
|
|
// Convert Base64 string to Uint8Array
|
|
function base64ToBuffer (base64Str) {
|
|
if (typeof window !== 'undefined' && window.atob) {
|
|
// Browser environment
|
|
const binaryString = window.atob(base64Str)
|
|
const bytes = new Uint8Array(binaryString.length)
|
|
for (let i = 0; i < binaryString.length; i++) {
|
|
bytes[i] = binaryString.charCodeAt(i)
|
|
}
|
|
return bytes
|
|
} else {
|
|
// Node.js environment
|
|
return new Uint8Array(Buffer.from(base64Str, 'base64'))
|
|
}
|
|
}
|
|
|
|
// Convert hex string to Uint8Array
|
|
function hexToBuffer (hexStr) {
|
|
const bytes = new Uint8Array(hexStr.length / 2)
|
|
for (let i = 0; i < hexStr.length; i += 2) {
|
|
bytes[i / 2] = parseInt(hexStr.substr(i, 2), 16)
|
|
}
|
|
return bytes
|
|
}
|
|
|
|
// Convert Uint8Array to hex string
|
|
function bufferToHex (buf) {
|
|
let hex = ''
|
|
for (let i = 0; i < buf.length; i++) {
|
|
const byte = buf[i]
|
|
hex += (byte < 16 ? '0' : '') + byte.toString(16)
|
|
}
|
|
return hex.toUpperCase()
|
|
}
|
|
|
|
// Convert Uint8Array to string
|
|
function bufferToString (buf, encoding, start, end) {
|
|
encoding = encoding || 'utf-8'
|
|
start = start || 0
|
|
end = end || buf.length
|
|
|
|
if (encoding !== 'utf-8' && encoding !== 'utf8') {
|
|
throw new Error('Unsupported encoding: ' + encoding)
|
|
}
|
|
|
|
const slice = buf.slice(start, end)
|
|
const decoder = new TextDecoder('utf-8')
|
|
return decoder.decode(slice)
|
|
}
|
|
|
|
// Write string to buffer, return number of bytes written
|
|
function writeString (buf, str, offset) {
|
|
offset = offset || 0
|
|
const encoded = stringToBuffer(str)
|
|
for (let i = 0; i < encoded.length && offset + i < buf.length; i++) {
|
|
buf[offset + i] = encoded[i]
|
|
}
|
|
return encoded.length
|
|
}
|
|
|
|
// Get byte length of a string
|
|
function byteLength (str) {
|
|
const encoder = new TextEncoder()
|
|
return encoder.encode(str).length
|
|
}
|
|
|
|
// Read big-endian 16-bit unsigned integer
|
|
function readUInt16BE (buf, offset) {
|
|
offset = offset || 0
|
|
return (buf[offset] << 8) | buf[offset + 1]
|
|
}
|
|
|
|
// Write big-endian 16-bit unsigned integer
|
|
function writeUInt16BE (buf, value, offset) {
|
|
offset = offset || 0
|
|
buf[offset] = (value >> 8) & 0xff
|
|
buf[offset + 1] = value & 0xff
|
|
}
|
|
|
|
// Read big-endian 32-bit unsigned integer
|
|
function readUInt32BE (buf, offset) {
|
|
offset = offset || 0
|
|
return ((buf[offset] << 24) | (buf[offset + 1] << 16) | (buf[offset + 2] << 8) | buf[offset + 3]) >>> 0
|
|
}
|
|
|
|
// Write big-endian 32-bit unsigned integer
|
|
function writeUInt32BE (buf, value, offset) {
|
|
offset = offset || 0
|
|
buf[offset] = (value >> 24) & 0xff
|
|
buf[offset + 1] = (value >> 16) & 0xff
|
|
buf[offset + 2] = (value >> 8) & 0xff
|
|
buf[offset + 3] = value & 0xff
|
|
}
|
|
|
|
// Read 8-bit unsigned integer
|
|
function readUInt8 (buf, offset) {
|
|
offset = offset || 0
|
|
return buf[offset]
|
|
}
|
|
|
|
// Write 8-bit unsigned integer
|
|
function writeUInt8 (buf, value, offset) {
|
|
offset = offset || 0
|
|
buf[offset] = value & 0xff
|
|
}
|
|
|
|
// Copy buffer contents
|
|
function bufferCopy (source, target, targetStart, sourceStart, sourceEnd) {
|
|
targetStart = targetStart || 0
|
|
sourceStart = sourceStart || 0
|
|
sourceEnd = sourceEnd !== undefined ? sourceEnd : source.length
|
|
|
|
for (let i = sourceStart; i < sourceEnd; i++) {
|
|
target[targetStart + (i - sourceStart)] = source[i]
|
|
}
|
|
}
|
|
|
|
// Concatenate multiple buffers
|
|
function bufferConcat (buffers, totalLength) {
|
|
if (!Array.isArray(buffers)) {
|
|
throw new Error('buffers must be an Array')
|
|
}
|
|
|
|
if (buffers.length === 0) {
|
|
return new Uint8Array(0)
|
|
}
|
|
|
|
totalLength = totalLength || buffers.reduce((sum, buf) => sum + buf.length, 0)
|
|
const result = new Uint8Array(totalLength)
|
|
|
|
let offset = 0
|
|
for (let i = 0; i < buffers.length; i++) {
|
|
const buf = buffers[i]
|
|
result.set(buf, offset)
|
|
offset += buf.length
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
module.exports = {
|
|
allocBuffer,
|
|
allocUnsafeBuffer,
|
|
isBuffer,
|
|
fromBuffer,
|
|
stringToBuffer,
|
|
base64ToBuffer,
|
|
hexToBuffer,
|
|
bufferToHex,
|
|
bufferToString,
|
|
writeString,
|
|
byteLength,
|
|
readUInt8,
|
|
writeUInt8,
|
|
readUInt16BE,
|
|
writeUInt16BE,
|
|
readUInt32BE,
|
|
writeUInt32BE,
|
|
bufferCopy,
|
|
bufferConcat
|
|
}
|