@msgpack/msgpack
Version:
MessagePack for JavaScript/ECMA-262
62 lines • 2.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CachedKeyDecoder = void 0;
const utf8_1 = require("./utils/utf8");
const DEFAULT_MAX_KEY_LENGTH = 16;
const DEFAULT_MAX_LENGTH_PER_KEY = 16;
class CachedKeyDecoder {
constructor(maxKeyLength = DEFAULT_MAX_KEY_LENGTH, maxLengthPerKey = DEFAULT_MAX_LENGTH_PER_KEY) {
this.maxKeyLength = maxKeyLength;
this.maxLengthPerKey = maxLengthPerKey;
this.hit = 0;
this.miss = 0;
// avoid `new Array(N)` to create a non-sparse array for performance.
this.caches = [];
for (let i = 0; i < this.maxKeyLength; i++) {
this.caches.push([]);
}
}
canBeCached(byteLength) {
return byteLength > 0 && byteLength <= this.maxKeyLength;
}
get(bytes, inputOffset, byteLength) {
const records = this.caches[byteLength - 1];
FIND_CHUNK: for (const record of records) {
const recordBytes = record.bytes;
for (let j = 0; j < byteLength; j++) {
if (recordBytes[j] !== bytes[inputOffset + j]) {
continue FIND_CHUNK;
}
}
return record.value;
}
return null;
}
store(bytes, value) {
const records = this.caches[bytes.length - 1];
const record = { bytes, value };
if (records.length >= this.maxLengthPerKey) {
// `records` are full!
// Set `record` to a randomized position.
records[(Math.random() * records.length) | 0] = record;
}
else {
records.push(record);
}
}
decode(bytes, inputOffset, byteLength) {
const cachedValue = this.get(bytes, inputOffset, byteLength);
if (cachedValue != null) {
this.hit++;
return cachedValue;
}
this.miss++;
const value = utf8_1.utf8DecodeJs(bytes, inputOffset, byteLength);
// Ensure to copy a slice of bytes because the byte may be NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer.
const slicedCopyOfBytes = Uint8Array.prototype.slice.call(bytes, inputOffset, inputOffset + byteLength);
this.store(slicedCopyOfBytes, value);
return value;
}
}
exports.CachedKeyDecoder = CachedKeyDecoder;
//# sourceMappingURL=CachedKeyDecoder.js.map