dotfiles/vscode/.vscode/extensions/randomfractalsinc.vscode-data-preview-2.3.0/node_modules/avsc/lib/utils.js
Errol Sancaktar ff17c17e23 vscode
2024-06-14 09:31:58 -06:00

960 lines
22 KiB
JavaScript

/* jshint node: true */
// TODO: Make long comparison impervious to precision loss.
// TODO: Optimize binary comparison methods.
'use strict';
/** Various utilities used across this library. */
var crypto = require('crypto');
var util = require('util');
// Shared buffer pool for all taps.
var POOL = new BufferPool(4096);
// Valid (field, type, and symbol) name regex.
var NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
/**
* Create a new empty buffer.
*
* @param size {Number} The buffer's size.
*/
function newBuffer(size) {
if (typeof Buffer.alloc == 'function') {
return Buffer.alloc(size);
} else {
return new Buffer(size);
}
}
/**
* Create a new buffer with the input contents.
*
* @param data {Array|String} The buffer's data.
* @param enc {String} Encoding, used if data is a string.
*/
function bufferFrom(data, enc) {
if (typeof Buffer.from == 'function') {
return Buffer.from(data, enc);
} else {
return new Buffer(data, enc);
}
}
/**
* Uppercase the first letter of a string.
*
* @param s {String} The string.
*/
function capitalize(s) { return s.charAt(0).toUpperCase() + s.slice(1); }
/**
* Compare two numbers.
*
* @param n1 {Number} The first one.
* @param n2 {Number} The second one.
*/
function compare(n1, n2) { return n1 === n2 ? 0 : (n1 < n2 ? -1 : 1); }
/**
* Get option or default if undefined.
*
* @param opts {Object} Options.
* @param key {String} Name of the option.
* @param def {...} Default value.
*
* This is useful mostly for true-ish defaults and false-ish values (where the
* usual `||` idiom breaks down).
*/
function getOption(opts, key, def) {
var value = opts[key];
return value === undefined ? def : value;
}
/**
* Compute a string's hash.
*
* @param str {String} The string to hash.
* @param algorithm {String} The algorithm used. Defaults to MD5.
*/
function getHash(str, algorithm) {
algorithm = algorithm || 'md5';
var hash = crypto.createHash(algorithm);
hash.end(str);
return hash.read();
}
/**
* Find index of value in array.
*
* @param arr {Array} Can also be a false-ish value.
* @param v {Object} Value to find.
*
* Returns -1 if not found, -2 if found multiple times.
*/
function singleIndexOf(arr, v) {
var pos = -1;
var i, l;
if (!arr) {
return -1;
}
for (i = 0, l = arr.length; i < l; i++) {
if (arr[i] === v) {
if (pos >= 0) {
return -2;
}
pos = i;
}
}
return pos;
}
/**
* Convert array to map.
*
* @param arr {Array} Elements.
* @param fn {Function} Function returning an element's key.
*/
function toMap(arr, fn) {
var obj = {};
var i, elem;
for (i = 0; i < arr.length; i++) {
elem = arr[i];
obj[fn(elem)] = elem;
}
return obj;
}
/**
* Convert map to array of values (polyfill for `Object.values`).
*
* @param obj {Object} Map.
*/
function objectValues(obj) {
return Object.keys(obj).map(function (key) { return obj[key]; });
}
/**
* Check whether an array has duplicates.
*
* @param arr {Array} The array.
* @param fn {Function} Optional function to apply to each element.
*/
function hasDuplicates(arr, fn) {
var obj = Object.create(null);
var i, l, elem;
for (i = 0, l = arr.length; i < l; i++) {
elem = arr[i];
if (fn) {
elem = fn(elem);
}
if (obj[elem]) {
return true;
}
obj[elem] = true;
}
return false;
}
/**
* Copy properties from one object to another.
*
* @param src {Object} The source object.
* @param dst {Object} The destination object.
* @param overwrite {Boolean} Whether to overwrite existing destination
* properties. Defaults to false.
*/
function copyOwnProperties(src, dst, overwrite) {
var names = Object.getOwnPropertyNames(src);
var i, l, name;
for (i = 0, l = names.length; i < l; i++) {
name = names[i];
if (!dst.hasOwnProperty(name) || overwrite) {
var descriptor = Object.getOwnPropertyDescriptor(src, name);
Object.defineProperty(dst, name, descriptor);
}
}
return dst;
}
/**
* Check whether a string is a valid Avro identifier.
*/
function isValidName(str) { return NAME_PATTERN.test(str); }
/**
* Verify and return fully qualified name.
*
* @param name {String} Full or short name. It can be prefixed with a dot to
* force global namespace.
* @param namespace {String} Optional namespace.
*/
function qualify(name, namespace) {
if (~name.indexOf('.')) {
name = name.replace(/^\./, ''); // Allow absolute referencing.
} else if (namespace) {
name = namespace + '.' + name;
}
name.split('.').forEach(function (part) {
if (!isValidName(part)) {
throw new Error(f('invalid name: %j', name));
}
});
return name;
}
/**
* Remove namespace from a name.
*
* @param name {String} Full or short name.
*/
function unqualify(name) {
var parts = name.split('.');
return parts[parts.length - 1];
}
/**
* Return the namespace implied by a name.
*
* @param name {String} Full or short name. If short, the returned namespace
* will be empty.
*/
function impliedNamespace(name) {
var match = /^(.*)\.[^.]+$/.exec(name);
return match ? match[1] : undefined;
}
/**
* Returns offset in the string of the end of JSON object (-1 if past the end).
*
* To keep the implementation simple, this function isn't a JSON validator. It
* will gladly return a result for invalid JSON (which is OK since that will be
* promptly rejected by the JSON parser). What matters is that it is guaranteed
* to return the correct end when presented with valid JSON.
*
* @param str {String} Input string containing serialized JSON..
* @param pos {Number} Starting position.
*/
function jsonEnd(str, pos) {
pos = pos | 0;
// Handle the case of a simple literal separately.
var c = str.charAt(pos++);
if (/[\d-]/.test(c)) {
while (/[eE\d.+-]/.test(str.charAt(pos))) {
pos++;
}
return pos;
} else if (/true|null/.test(str.slice(pos - 1, pos + 3))) {
return pos + 3;
} else if (/false/.test(str.slice(pos - 1, pos + 4))) {
return pos + 4;
}
// String, object, or array.
var depth = 0;
var literal = false;
do {
switch (c) {
case '{':
case '[':
if (!literal) { depth++; }
break;
case '}':
case ']':
if (!literal && !--depth) {
return pos;
}
break;
case '"':
literal = !literal;
if (!depth && !literal) {
return pos;
}
break;
case '\\':
pos++; // Skip the next character.
}
} while ((c = str.charAt(pos++)));
return -1;
}
/** "Abstract" function to help with "subclassing". */
function abstractFunction() { throw new Error('abstract'); }
/** Batch-deprecate "getters" from an object's prototype. */
function addDeprecatedGetters(obj, props) {
var proto = obj.prototype;
var i, l, prop, getter;
for (i = 0, l = props.length; i < l; i++) {
prop = props[i];
getter = 'get' + capitalize(prop);
proto[getter] = util.deprecate(
createGetter(prop),
'use `.' + prop + '` instead of `.' + getter + '()`'
);
}
function createGetter(prop) {
return function () {
var delegate = this[prop];
return typeof delegate == 'function' ?
delegate.apply(this, arguments) :
delegate;
};
}
}
/**
* Simple buffer pool to avoid allocating many small buffers.
*
* This provides significant speedups in recent versions of node (6+).
*/
function BufferPool(len) {
this._len = len | 0;
this._pos = 0;
this._slab = newBuffer(this._len);
}
BufferPool.prototype.alloc = function (len) {
if (len < 0) {
throw new Error('negative length');
}
var maxLen = this._len;
if (len > maxLen) {
return newBuffer(len);
}
if (this._pos + len > maxLen) {
this._slab = newBuffer(maxLen);
this._pos = 0;
}
return this._slab.slice(this._pos, this._pos += len);
};
/**
* Generator of random things.
*
* Inspired by: http://stackoverflow.com/a/424445/1062617
*/
function Lcg(seed) {
var a = 1103515245;
var c = 12345;
var m = Math.pow(2, 31);
var state = Math.floor(seed || Math.random() * (m - 1));
this._max = m;
this._nextInt = function () { return state = (a * state + c) % m; };
}
Lcg.prototype.nextBoolean = function () {
// jshint -W018
return !!(this._nextInt() % 2);
};
Lcg.prototype.nextInt = function (start, end) {
if (end === undefined) {
end = start;
start = 0;
}
end = end === undefined ? this._max : end;
return start + Math.floor(this.nextFloat() * (end - start));
};
Lcg.prototype.nextFloat = function (start, end) {
if (end === undefined) {
end = start;
start = 0;
}
end = end === undefined ? 1 : end;
return start + (end - start) * this._nextInt() / this._max;
};
Lcg.prototype.nextString = function(len, flags) {
len |= 0;
flags = flags || 'aA';
var mask = '';
if (flags.indexOf('a') > -1) {
mask += 'abcdefghijklmnopqrstuvwxyz';
}
if (flags.indexOf('A') > -1) {
mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
}
if (flags.indexOf('#') > -1) {
mask += '0123456789';
}
if (flags.indexOf('!') > -1) {
mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\';
}
var result = [];
for (var i = 0; i < len; i++) {
result.push(this.choice(mask));
}
return result.join('');
};
Lcg.prototype.nextBuffer = function (len) {
var arr = [];
var i;
for (i = 0; i < len; i++) {
arr.push(this.nextInt(256));
}
return bufferFrom(arr);
};
Lcg.prototype.choice = function (arr) {
var len = arr.length;
if (!len) {
throw new Error('choosing from empty array');
}
return arr[this.nextInt(len)];
};
/**
* Ordered queue which returns items consecutively.
*
* This is actually a heap by index, with the added requirements that elements
* can only be retrieved consecutively.
*/
function OrderedQueue() {
this._index = 0;
this._items = [];
}
OrderedQueue.prototype.push = function (item) {
var items = this._items;
var i = items.length | 0;
var j;
items.push(item);
while (i > 0 && items[i].index < items[j = ((i - 1) >> 1)].index) {
item = items[i];
items[i] = items[j];
items[j] = item;
i = j;
}
};
OrderedQueue.prototype.pop = function () {
var items = this._items;
var len = (items.length - 1) | 0;
var first = items[0];
if (!first || first.index > this._index) {
return null;
}
this._index++;
if (!len) {
items.pop();
return first;
}
items[0] = items.pop();
var mid = len >> 1;
var i = 0;
var i1, i2, j, item, c, c1, c2;
while (i < mid) {
item = items[i];
i1 = (i << 1) + 1;
i2 = (i + 1) << 1;
c1 = items[i1];
c2 = items[i2];
if (!c2 || c1.index <= c2.index) {
c = c1;
j = i1;
} else {
c = c2;
j = i2;
}
if (c.index >= item.index) {
break;
}
items[j] = item;
items[i] = c;
i = j;
}
return first;
};
/**
* A tap is a buffer which remembers what has been already read.
*
* It is optimized for performance, at the cost of failing silently when
* overflowing the buffer. This is a purposeful trade-off given the expected
* rarity of this case and the large performance hit necessary to enforce
* validity. See `isValid` below for more information.
*/
function Tap(buf, pos) {
this.buf = buf;
this.pos = pos | 0;
if (this.pos < 0) {
throw new Error('negative offset');
}
}
/**
* Check that the tap is in a valid state.
*
* For efficiency reasons, none of the methods below will fail if an overflow
* occurs (either read, skip, or write). For this reason, it is up to the
* caller to always check that the read, skip, or write was valid by calling
* this method.
*/
Tap.prototype.isValid = function () { return this.pos <= this.buf.length; };
Tap.prototype._invalidate = function () { this.pos = this.buf.length + 1; };
// Read, skip, write methods.
//
// These should fail silently when the buffer overflows. Note this is only
// required to be true when the functions are decoding valid objects. For
// example errors will still be thrown if a bad count is read, leading to a
// negative position offset (which will typically cause a failure in
// `readFixed`).
Tap.prototype.readBoolean = function () { return !!this.buf[this.pos++]; };
Tap.prototype.skipBoolean = function () { this.pos++; };
Tap.prototype.writeBoolean = function (b) { this.buf[this.pos++] = !!b; };
Tap.prototype.readInt = Tap.prototype.readLong = function () {
var n = 0;
var k = 0;
var buf = this.buf;
var b, h, f, fk;
do {
b = buf[this.pos++];
h = b & 0x80;
n |= (b & 0x7f) << k;
k += 7;
} while (h && k < 28);
if (h) {
// Switch to float arithmetic, otherwise we might overflow.
f = n;
fk = 268435456; // 2 ** 28.
do {
b = buf[this.pos++];
f += (b & 0x7f) * fk;
fk *= 128;
} while (b & 0x80);
return (f % 2 ? -(f + 1) : f) / 2;
}
return (n >> 1) ^ -(n & 1);
};
Tap.prototype.skipInt = Tap.prototype.skipLong = function () {
var buf = this.buf;
while (buf[this.pos++] & 0x80) {}
};
Tap.prototype.writeInt = Tap.prototype.writeLong = function (n) {
var buf = this.buf;
var f, m;
if (n >= -1073741824 && n < 1073741824) {
// Won't overflow, we can use integer arithmetic.
m = n >= 0 ? n << 1 : (~n << 1) | 1;
do {
buf[this.pos] = m & 0x7f;
m >>= 7;
} while (m && (buf[this.pos++] |= 0x80));
} else {
// We have to use slower floating arithmetic.
f = n >= 0 ? n * 2 : (-n * 2) - 1;
do {
buf[this.pos] = f & 0x7f;
f /= 128;
} while (f >= 1 && (buf[this.pos++] |= 0x80));
}
this.pos++;
};
Tap.prototype.readFloat = function () {
var buf = this.buf;
var pos = this.pos;
this.pos += 4;
if (this.pos > buf.length) {
return 0;
}
return this.buf.readFloatLE(pos);
};
Tap.prototype.skipFloat = function () { this.pos += 4; };
Tap.prototype.writeFloat = function (f) {
var buf = this.buf;
var pos = this.pos;
this.pos += 4;
if (this.pos > buf.length) {
return;
}
return this.buf.writeFloatLE(f, pos);
};
Tap.prototype.readDouble = function () {
var buf = this.buf;
var pos = this.pos;
this.pos += 8;
if (this.pos > buf.length) {
return 0;
}
return this.buf.readDoubleLE(pos);
};
Tap.prototype.skipDouble = function () { this.pos += 8; };
Tap.prototype.writeDouble = function (d) {
var buf = this.buf;
var pos = this.pos;
this.pos += 8;
if (this.pos > buf.length) {
return;
}
return this.buf.writeDoubleLE(d, pos);
};
Tap.prototype.readFixed = function (len) {
var pos = this.pos;
this.pos += len;
if (this.pos > this.buf.length) {
return;
}
var fixed = POOL.alloc(len);
this.buf.copy(fixed, 0, pos, pos + len);
return fixed;
};
Tap.prototype.skipFixed = function (len) { this.pos += len; };
Tap.prototype.writeFixed = function (buf, len) {
len = len || buf.length;
var pos = this.pos;
this.pos += len;
if (this.pos > this.buf.length) {
return;
}
buf.copy(this.buf, pos, 0, len);
};
Tap.prototype.readBytes = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return;
}
return this.readFixed(len);
};
Tap.prototype.skipBytes = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return;
}
this.pos += len;
};
Tap.prototype.writeBytes = function (buf) {
var len = buf.length;
this.writeLong(len);
this.writeFixed(buf, len);
};
/* istanbul ignore else */
if (typeof Buffer.prototype.utf8Slice == 'function') {
// Use this optimized function when available.
Tap.prototype.readString = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return '';
}
var pos = this.pos;
var buf = this.buf;
this.pos += len;
if (this.pos > buf.length) {
return;
}
return this.buf.utf8Slice(pos, pos + len);
};
} else {
Tap.prototype.readString = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return '';
}
var pos = this.pos;
var buf = this.buf;
this.pos += len;
if (this.pos > buf.length) {
return;
}
return this.buf.slice(pos, pos + len).toString();
};
}
Tap.prototype.skipString = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return;
}
this.pos += len;
};
Tap.prototype.writeString = function (s) {
var len = Buffer.byteLength(s);
var buf = this.buf;
this.writeLong(len);
var pos = this.pos;
this.pos += len;
if (this.pos > buf.length) {
return;
}
if (len > 64 && typeof Buffer.prototype.utf8Write == 'function') {
// This method is roughly 50% faster than the manual implementation below
// for long strings (which is itself faster than the generic `Buffer#write`
// at least in most browsers, where `utf8Write` is not available).
buf.utf8Write(s, pos, len);
} else {
var i, l, c1, c2;
for (i = 0, l = len; i < l; i++) {
c1 = s.charCodeAt(i);
if (c1 < 0x80) {
buf[pos++] = c1;
} else if (c1 < 0x800) {
buf[pos++] = c1 >> 6 | 0xc0;
buf[pos++] = c1 & 0x3f | 0x80;
} else if (
(c1 & 0xfc00) === 0xd800 &&
((c2 = s.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
) {
c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
i++;
buf[pos++] = c1 >> 18 | 0xf0;
buf[pos++] = c1 >> 12 & 0x3f | 0x80;
buf[pos++] = c1 >> 6 & 0x3f | 0x80;
buf[pos++] = c1 & 0x3f | 0x80;
} else {
buf[pos++] = c1 >> 12 | 0xe0;
buf[pos++] = c1 >> 6 & 0x3f | 0x80;
buf[pos++] = c1 & 0x3f | 0x80;
}
}
}
};
/* istanbul ignore else */
if (typeof Buffer.prototype.latin1Write == 'function') {
// `binaryWrite` has been renamed to `latin1Write` in Node v6.4.0, see
// https://github.com/nodejs/node/pull/7111. Note that the `'binary'`
// encoding argument still works however.
Tap.prototype.writeBinary = function (str, len) {
var pos = this.pos;
this.pos += len;
if (this.pos > this.buf.length) {
return;
}
this.buf.latin1Write(str, pos, len);
};
} else if (typeof Buffer.prototype.binaryWrite == 'function') {
Tap.prototype.writeBinary = function (str, len) {
var pos = this.pos;
this.pos += len;
if (this.pos > this.buf.length) {
return;
}
this.buf.binaryWrite(str, pos, len);
};
} else {
// Slowest implementation.
Tap.prototype.writeBinary = function (s, len) {
var pos = this.pos;
this.pos += len;
if (this.pos > this.buf.length) {
return;
}
this.buf.write(s, pos, len, 'binary');
};
}
// Binary comparison methods.
//
// These are not guaranteed to consume the objects they are comparing when
// returning a non-zero result (allowing for performance benefits), so no other
// operations should be done on either tap after a compare returns a non-zero
// value. Also, these methods do not have the same silent failure requirement
// as read, skip, and write since they are assumed to be called on valid
// buffers.
Tap.prototype.matchBoolean = function (tap) {
return this.buf[this.pos++] - tap.buf[tap.pos++];
};
Tap.prototype.matchInt = Tap.prototype.matchLong = function (tap) {
var n1 = this.readLong();
var n2 = tap.readLong();
return n1 === n2 ? 0 : (n1 < n2 ? -1 : 1);
};
Tap.prototype.matchFloat = function (tap) {
var n1 = this.readFloat();
var n2 = tap.readFloat();
return n1 === n2 ? 0 : (n1 < n2 ? -1 : 1);
};
Tap.prototype.matchDouble = function (tap) {
var n1 = this.readDouble();
var n2 = tap.readDouble();
return n1 === n2 ? 0 : (n1 < n2 ? -1 : 1);
};
Tap.prototype.matchFixed = function (tap, len) {
return this.readFixed(len).compare(tap.readFixed(len));
};
Tap.prototype.matchBytes = Tap.prototype.matchString = function (tap) {
var l1 = this.readLong();
var p1 = this.pos;
this.pos += l1;
var l2 = tap.readLong();
var p2 = tap.pos;
tap.pos += l2;
var b1 = this.buf.slice(p1, this.pos);
var b2 = tap.buf.slice(p2, tap.pos);
return b1.compare(b2);
};
// Functions for supporting custom long classes.
//
// The two following methods allow the long implementations to not have to
// worry about Avro's zigzag encoding, we directly expose longs as unpacked.
Tap.prototype.unpackLongBytes = function () {
var res = newBuffer(8);
var n = 0;
var i = 0; // Byte index in target buffer.
var j = 6; // Bit offset in current target buffer byte.
var buf = this.buf;
var b, neg;
b = buf[this.pos++];
neg = b & 1;
res.fill(0);
n |= (b & 0x7f) >> 1;
while (b & 0x80) {
b = buf[this.pos++];
n |= (b & 0x7f) << j;
j += 7;
if (j >= 8) {
// Flush byte.
j -= 8;
res[i++] = n;
n >>= 8;
}
}
res[i] = n;
if (neg) {
invert(res, 8);
}
return res;
};
Tap.prototype.packLongBytes = function (buf) {
var neg = (buf[7] & 0x80) >> 7;
var res = this.buf;
var j = 1;
var k = 0;
var m = 3;
var n;
if (neg) {
invert(buf, 8);
n = 1;
} else {
n = 0;
}
var parts = [
buf.readUIntLE(0, 3),
buf.readUIntLE(3, 3),
buf.readUIntLE(6, 2)
];
// Not reading more than 24 bits because we need to be able to combine the
// "carry" bits from the previous part and JavaScript only supports bitwise
// operations on 32 bit integers.
while (m && !parts[--m]) {} // Skip trailing 0s.
// Leading parts (if any), we never bail early here since we need the
// continuation bit to be set.
while (k < m) {
n |= parts[k++] << j;
j += 24;
while (j > 7) {
res[this.pos++] = (n & 0x7f) | 0x80;
n >>= 7;
j -= 7;
}
}
// Final part, similar to normal packing aside from the initial offset.
n |= parts[m] << j;
do {
res[this.pos] = n & 0x7f;
n >>= 7;
} while (n && (res[this.pos++] |= 0x80));
this.pos++;
// Restore original buffer (could make this optional?).
if (neg) {
invert(buf, 8);
}
};
// Helpers.
/**
* Invert all bits in a buffer.
*
* @param buf {Buffer} Non-empty buffer to invert.
* @param len {Number} Buffer length (must be positive).
*/
function invert(buf, len) {
while (len--) {
buf[len] = ~buf[len];
}
}
module.exports = {
abstractFunction: abstractFunction,
addDeprecatedGetters: addDeprecatedGetters,
bufferFrom: bufferFrom,
capitalize: capitalize,
copyOwnProperties: copyOwnProperties,
getHash: getHash,
compare: compare,
getOption: getOption,
impliedNamespace: impliedNamespace,
isValidName: isValidName,
jsonEnd: jsonEnd,
newBuffer: newBuffer,
objectValues: objectValues,
qualify: qualify,
toMap: toMap,
singleIndexOf: singleIndexOf,
hasDuplicates: hasDuplicates,
unqualify: unqualify,
BufferPool: BufferPool,
Lcg: Lcg,
OrderedQueue: OrderedQueue,
Tap: Tap
};