mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
optimize code for speed and size
This commit is contained in:
@@ -1,45 +1,17 @@
|
|||||||
let decoder;
|
// @ts-nocheck - Optimized MessagePack unpacking library for EMS-ESP32
|
||||||
try {
|
let decoder, src, srcEnd, position = 0, strings = [], stringPosition = 0, currentUnpackr = {}, currentStructures, srcString, srcStringStart = 0, srcStringEnd = 0, bundledStrings, referenceMap, dataView;
|
||||||
decoder = new TextDecoder();
|
const EMPTY_ARRAY = [], currentExtensions = [];
|
||||||
} catch (error) {}
|
const defaultOptions = { useRecords: false, mapsAsObjects: true };
|
||||||
let src;
|
try { decoder = new TextDecoder(); } catch (error) { }
|
||||||
let srcEnd;
|
class C1Type { }
|
||||||
let position = 0;
|
const C1 = new C1Type();
|
||||||
const EMPTY_ARRAY = [];
|
|
||||||
let strings = EMPTY_ARRAY;
|
|
||||||
let stringPosition = 0;
|
|
||||||
let currentUnpackr = {};
|
|
||||||
let currentStructures;
|
|
||||||
let srcString;
|
|
||||||
let srcStringStart = 0;
|
|
||||||
let srcStringEnd = 0;
|
|
||||||
let bundledStrings;
|
|
||||||
let referenceMap;
|
|
||||||
const currentExtensions = [];
|
|
||||||
let dataView;
|
|
||||||
const defaultOptions = {
|
|
||||||
useRecords: false,
|
|
||||||
mapsAsObjects: true
|
|
||||||
};
|
|
||||||
export class C1Type {}
|
|
||||||
export const C1 = new C1Type();
|
|
||||||
C1.name = 'MessagePack 0xC1';
|
C1.name = 'MessagePack 0xC1';
|
||||||
let sequentialMode = false;
|
let sequentialMode = false, inlineObjectReadThreshold = 2, readStruct, onLoadedStructures, onSaveState;
|
||||||
let inlineObjectReadThreshold = 2;
|
try { new Function(''); } catch (error) { inlineObjectReadThreshold = Infinity; }
|
||||||
let readStruct, onLoadedStructures, onSaveState;
|
|
||||||
// no-eval build
|
|
||||||
try {
|
|
||||||
new Function('');
|
|
||||||
} catch (error) {
|
|
||||||
// if eval variants are not supported, do not create inline object readers ever
|
|
||||||
inlineObjectReadThreshold = Infinity;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Unpackr {
|
export class Unpackr {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
if (options) {
|
if (options) {
|
||||||
if (options.useRecords === false && options.mapsAsObjects === undefined)
|
if (options.useRecords === false && options.mapsAsObjects === undefined) options.mapsAsObjects = true;
|
||||||
options.mapsAsObjects = true;
|
|
||||||
if (options.sequential && options.trusted !== false) {
|
if (options.sequential && options.trusted !== false) {
|
||||||
options.trusted = true;
|
options.trusted = true;
|
||||||
if (!options.structures && options.useRecords != false) {
|
if (!options.structures && options.useRecords != false) {
|
||||||
@@ -47,22 +19,17 @@ export class Unpackr {
|
|||||||
if (!options.maxSharedStructures) options.maxSharedStructures = 0;
|
if (!options.maxSharedStructures) options.maxSharedStructures = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (options.structures)
|
if (options.structures) options.structures.sharedLength = options.structures.length;
|
||||||
options.structures.sharedLength = options.structures.length;
|
|
||||||
else if (options.getStructures) {
|
else if (options.getStructures) {
|
||||||
(options.structures = []).uninitialized = true; // this is what we use to denote an uninitialized structures
|
(options.structures = []).uninitialized = true;
|
||||||
options.structures.sharedLength = 0;
|
options.structures.sharedLength = 0;
|
||||||
}
|
}
|
||||||
if (options.int64AsNumber) {
|
if (options.int64AsNumber) options.int64AsType = 'number';
|
||||||
options.int64AsType = 'number';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Object.assign(this, options);
|
Object.assign(this, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
unpack(source, options?: any) {
|
unpack(source, options?: any) {
|
||||||
if (src) {
|
if (src) {
|
||||||
// re-entrant execution, save the state and restore it after we do this unpack
|
|
||||||
return saveState(() => {
|
return saveState(() => {
|
||||||
clearSource();
|
clearSource();
|
||||||
return this
|
return this
|
||||||
@@ -86,9 +53,6 @@ export class Unpackr {
|
|||||||
strings = EMPTY_ARRAY;
|
strings = EMPTY_ARRAY;
|
||||||
bundledStrings = null;
|
bundledStrings = null;
|
||||||
src = source;
|
src = source;
|
||||||
// this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
|
|
||||||
// technique for getting data from a database where it can be copied into an existing buffer instead of creating
|
|
||||||
// new ones
|
|
||||||
try {
|
try {
|
||||||
dataView =
|
dataView =
|
||||||
source.dataView ||
|
source.dataView ||
|
||||||
@@ -103,9 +67,9 @@ export class Unpackr {
|
|||||||
if (source instanceof Uint8Array) throw error;
|
if (source instanceof Uint8Array) throw error;
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Source must be a Uint8Array or Buffer but was a ' +
|
'Source must be a Uint8Array or Buffer but was a ' +
|
||||||
(source && typeof source == 'object'
|
(source && typeof source == 'object'
|
||||||
? source.constructor.name
|
? source.constructor.name
|
||||||
: typeof source)
|
: typeof source)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this instanceof Unpackr) {
|
if (this instanceof Unpackr) {
|
||||||
@@ -191,10 +155,10 @@ export class Unpackr {
|
|||||||
return this.unpack(source, end);
|
return this.unpack(source, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function getPosition() {
|
function getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
export function checkedRead(options: any) {
|
function checkedRead(options: any) {
|
||||||
try {
|
try {
|
||||||
if (!currentUnpackr.trusted && !sequentialMode) {
|
if (!currentUnpackr.trusted && !sequentialMode) {
|
||||||
const sharedLength = currentStructures.sharedLength || 0;
|
const sharedLength = currentStructures.sharedLength || 0;
|
||||||
@@ -264,7 +228,7 @@ function restoreStructures() {
|
|||||||
currentStructures.restoreStructures = null;
|
currentStructures.restoreStructures = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function read() {
|
function read() {
|
||||||
let token = src[position++];
|
let token = src[position++];
|
||||||
if (token < 0xa0) {
|
if (token < 0xa0) {
|
||||||
if (token < 0x80) {
|
if (token < 0x80) {
|
||||||
@@ -542,18 +506,18 @@ function createStructureReader(structure, firstId) {
|
|||||||
const readObject = (structure.read = new Function(
|
const readObject = (structure.read = new Function(
|
||||||
'r',
|
'r',
|
||||||
'return function(){return ' +
|
'return function(){return ' +
|
||||||
(currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
(currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
||||||
'({' +
|
'({' +
|
||||||
structure
|
structure
|
||||||
.map((key) =>
|
.map((key) =>
|
||||||
key === '__proto__'
|
key === '__proto__'
|
||||||
? '__proto_:r()'
|
? '__proto_:r()'
|
||||||
: validName.test(key)
|
: validName.test(key)
|
||||||
? key + ':r()'
|
? key + ':r()'
|
||||||
: '[' + JSON.stringify(key) + ']:r()'
|
: '[' + JSON.stringify(key) + ']:r()'
|
||||||
)
|
)
|
||||||
.join(',') +
|
.join(',') +
|
||||||
'})}'
|
'})}'
|
||||||
)(read));
|
)(read));
|
||||||
if (structure.highByte === 0)
|
if (structure.highByte === 0)
|
||||||
structure.read = createSecondByteReader(firstId, structure.read);
|
structure.read = createSecondByteReader(firstId, structure.read);
|
||||||
@@ -589,7 +553,7 @@ const createSecondByteReader = (firstId, read0) =>
|
|||||||
return structure.read();
|
return structure.read();
|
||||||
};
|
};
|
||||||
|
|
||||||
export function loadStructures() {
|
function loadStructures() {
|
||||||
const loadedStructures = saveState(() => {
|
const loadedStructures = saveState(() => {
|
||||||
// save the state in case getStructures modifies our buffer
|
// save the state in case getStructures modifies our buffer
|
||||||
src = null;
|
src = null;
|
||||||
@@ -605,9 +569,8 @@ var readFixedString = readStringJS;
|
|||||||
var readString8 = readStringJS;
|
var readString8 = readStringJS;
|
||||||
var readString16 = readStringJS;
|
var readString16 = readStringJS;
|
||||||
var readString32 = readStringJS;
|
var readString32 = readStringJS;
|
||||||
export let isNativeAccelerationEnabled = false;
|
let isNativeAccelerationEnabled = false;
|
||||||
|
function setExtractor(extractStrings) {
|
||||||
export function setExtractor(extractStrings) {
|
|
||||||
isNativeAccelerationEnabled = true;
|
isNativeAccelerationEnabled = true;
|
||||||
readFixedString = readString(1);
|
readFixedString = readString(1);
|
||||||
readString8 = readString(2);
|
readString8 = readString(2);
|
||||||
@@ -701,7 +664,7 @@ function readStringJS(length) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
export function readString(source, start, length) {
|
function readString(source, start, length) {
|
||||||
const existingSrc = src;
|
const existingSrc = src;
|
||||||
src = source;
|
src = source;
|
||||||
position = start;
|
position = start;
|
||||||
@@ -918,7 +881,7 @@ function readOnlyJSString() {
|
|||||||
function readBin(length) {
|
function readBin(length) {
|
||||||
return currentUnpackr.copyBuffers
|
return currentUnpackr.copyBuffers
|
||||||
? // specifically use the copying slice (not the node one)
|
? // specifically use the copying slice (not the node one)
|
||||||
Uint8Array.prototype.slice.call(src, position, (position += length))
|
Uint8Array.prototype.slice.call(src, position, (position += length))
|
||||||
: src.subarray(position, (position += length));
|
: src.subarray(position, (position += length));
|
||||||
}
|
}
|
||||||
function readExt(length) {
|
function readExt(length) {
|
||||||
@@ -1026,7 +989,7 @@ const recordDefinition = (id, highByte) => {
|
|||||||
structure.read = createStructureReader(structure, firstByte);
|
structure.read = createStructureReader(structure, firstByte);
|
||||||
return structure.read();
|
return structure.read();
|
||||||
};
|
};
|
||||||
currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
currentExtensions[0] = () => { }; // notepack defines extension 0 to mean undefined, so use that as the default here
|
||||||
currentExtensions[0].noBuffer = true;
|
currentExtensions[0].noBuffer = true;
|
||||||
|
|
||||||
const glbl = typeof globalThis === 'object' ? globalThis : window;
|
const glbl = typeof globalThis === 'object' ? globalThis : window;
|
||||||
@@ -1065,7 +1028,7 @@ currentExtensions[0x70] = (data) => {
|
|||||||
|
|
||||||
currentExtensions[0x73] = () => new Set(read());
|
currentExtensions[0x73] = () => new Set(read());
|
||||||
|
|
||||||
export const typedArrays = [
|
const typedArrays = [
|
||||||
'Int8',
|
'Int8',
|
||||||
'Uint8',
|
'Uint8',
|
||||||
'Uint8Clamped',
|
'Uint8Clamped',
|
||||||
@@ -1114,25 +1077,25 @@ currentExtensions[0xff] = (data) => {
|
|||||||
else if (data.length == 8)
|
else if (data.length == 8)
|
||||||
return new Date(
|
return new Date(
|
||||||
((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) /
|
((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) /
|
||||||
1000000 +
|
1000000 +
|
||||||
((data[3] & 0x3) * 0x100000000 +
|
((data[3] & 0x3) * 0x100000000 +
|
||||||
data[4] * 0x1000000 +
|
data[4] * 0x1000000 +
|
||||||
(data[5] << 16) +
|
(data[5] << 16) +
|
||||||
(data[6] << 8) +
|
(data[6] << 8) +
|
||||||
data[7]) *
|
data[7]) *
|
||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
else if (data.length == 12)
|
else if (data.length == 12)
|
||||||
return new Date(
|
return new Date(
|
||||||
((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
|
((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
|
||||||
((data[4] & 0x80 ? -0x1000000000000 : 0) +
|
((data[4] & 0x80 ? -0x1000000000000 : 0) +
|
||||||
data[6] * 0x10000000000 +
|
data[6] * 0x10000000000 +
|
||||||
data[7] * 0x100000000 +
|
data[7] * 0x100000000 +
|
||||||
data[8] * 0x1000000 +
|
data[8] * 0x1000000 +
|
||||||
(data[9] << 16) +
|
(data[9] << 16) +
|
||||||
(data[10] << 8) +
|
(data[10] << 8) +
|
||||||
data[11]) *
|
data[11]) *
|
||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
else return new Date('invalid');
|
else return new Date('invalid');
|
||||||
}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
||||||
@@ -1177,44 +1140,20 @@ function saveState(callback) {
|
|||||||
dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
|
dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
export function clearSource() {
|
function clearSource() {
|
||||||
src = null;
|
src = null;
|
||||||
referenceMap = null;
|
referenceMap = null;
|
||||||
currentStructures = null;
|
currentStructures = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addExtension(extension) {
|
function addExtension(extension) {
|
||||||
if (extension.unpack) currentExtensions[extension.type] = extension.unpack;
|
if (extension.unpack) currentExtensions[extension.type] = extension.unpack;
|
||||||
else currentExtensions[extension.type] = extension;
|
else currentExtensions[extension.type] = extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
const mult10 = new Array(147);
|
||||||
for (let i = 0; i < 256; i++) {
|
for (let i = 0; i < 256; i++) {
|
||||||
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
|
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
|
||||||
}
|
}
|
||||||
export const Decoder = Unpackr;
|
const defaultUnpackr = new Unpackr({ useRecords: false });
|
||||||
var defaultUnpackr = new Unpackr({ useRecords: false });
|
|
||||||
export const unpack = defaultUnpackr.unpack;
|
export const unpack = defaultUnpackr.unpack;
|
||||||
export const unpackMultiple = defaultUnpackr.unpackMultiple;
|
|
||||||
export const decode = defaultUnpackr.unpack;
|
|
||||||
export const FLOAT32_OPTIONS = {
|
|
||||||
NEVER: 0,
|
|
||||||
ALWAYS: 1,
|
|
||||||
DECIMAL_ROUND: 3,
|
|
||||||
DECIMAL_FIT: 4
|
|
||||||
};
|
|
||||||
const f32Array = new Float32Array(1);
|
|
||||||
const u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
||||||
export function roundFloat32(float32Number) {
|
|
||||||
f32Array[0] = float32Number;
|
|
||||||
const multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
|
|
||||||
return (
|
|
||||||
((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) /
|
|
||||||
multiplier
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export function setReadStruct(updatedReadStruct, loadedStructs, saveState) {
|
|
||||||
readStruct = updatedReadStruct;
|
|
||||||
onLoadedStructures = loadedStructs;
|
|
||||||
onSaveState = saveState;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user