Last active
January 10, 2023 13:25
-
-
Save vipertechofficial/c5abdabd871b946472bdb272c3049dc6 to your computer and use it in GitHub Desktop.
Working on a FASTER BYTE array from/to OBJECT SERIALIZER with Head (three), Neck (properties heap) and Body (values heap)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2023 Affolter Matias | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all | |
* copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
* SOFTWARE. | |
*/ | |
var Nuclei = (function () { | |
var Nuclei = {}; | |
var Decoder = new TextDecoder(); | |
var Encoder = new TextEncoder(); | |
Nuclei.Encoder = Encoder; | |
Nuclei.Decoder = Decoder; | |
var TYPES = [ | |
{ | |
name: "undefined", | |
id: 0, | |
fixed: true, | |
bytes: 0, | |
enc: function () { | |
return new ArrayBuffer(0); | |
}, | |
dec: function () { | |
return undefined; | |
}, | |
is: function (d) { | |
return typeof d == "undefined"; | |
} | |
}, | |
{ | |
name: "null", | |
id: 1, | |
fixed: true, | |
bytes: 0, | |
enc: function () { | |
return new ArrayBuffer(0); | |
}, | |
dec: function () { | |
return null; | |
}, | |
is: function (d) { | |
return d === null; | |
} | |
}, | |
{ | |
name: "NaN", | |
id: 2, | |
fixed: true, | |
bytes: 0, | |
enc: function () { | |
return new ArrayBuffer(0); | |
}, | |
dec: function () { | |
return NaN; | |
}, | |
is: function (d) { | |
return d === NaN; | |
} | |
}, | |
{ | |
name: "Infinity", | |
id: 3, | |
fixed: true, | |
bytes: 0, | |
enc: function () { | |
return new ArrayBuffer(0); | |
}, | |
dec: function () { | |
return Infinity; | |
}, | |
is: function (d) { | |
return d === Infinity; | |
} | |
}, | |
{ | |
name: "Boolean", | |
id: 4, | |
fixed: true, | |
bytes: 1, | |
enc: function (d) { | |
return Uint8Array.from(d).buffer; | |
}, | |
dec: function (d) { | |
return d[0] > 0; | |
}, | |
is: function (d) { | |
return d === true || d === false; | |
} | |
}, | |
{ | |
name: "Int32", | |
id: 5, | |
fixed: true, | |
bytes: 4, | |
enc: function (d) { | |
return Int32Array.of(d).buffer; | |
}, | |
dec: function (b) { | |
return new Int32Array(b)[0]; | |
}, | |
is: function (d) { | |
return typeof d == "number" && d < 0; | |
} | |
}, | |
{ | |
name: "Uint32", | |
id: 6, | |
fixed: true, | |
bytes: 4, | |
enc: function (d) { | |
return Uint32Array.of(d).buffer; | |
}, | |
dec: function (b) { | |
return new Uint32Array(b)[0]; | |
}, | |
is: function (d) { | |
return typeof d == "number" && d > 0 && d < 0xffffffff; | |
} | |
}, | |
{ | |
name: "Float32", | |
id: 7, | |
fixed: true, | |
bytes: 4, | |
enc: function (d) { | |
return Float32Array.of(d).buffer; | |
}, | |
dec: function (b) { | |
return new Float32Array(b)[0]; | |
}, | |
is: function (d) { | |
return typeof d == "number" && (d | 0) * 10 != ((d * 10) | 0); | |
} | |
}, | |
{ | |
name: "BigInt64", | |
id: 8, | |
fixed: true, | |
bytes: 8, | |
enc: function (d) { | |
return BigInt64Array.of(d).buffer; | |
}, | |
dec: function (b) { | |
return new BigInt64Array(b)[0]; | |
}, | |
is: function (d) { | |
return d > 0xffffffff; | |
} | |
}, | |
{ | |
name: "Float64", | |
id: 9, | |
fixed: true, | |
bytes: 8, | |
enc: function (d) { | |
return Float64Array.of(d).buffer; | |
}, | |
dec: function (b) { | |
return new Float64Array(b)[0]; | |
}, | |
is: function (d) { | |
return typeof d == "number" && (d | 0) * 10 != ((d * 10) | 0); | |
} | |
}, | |
{ | |
name: "String", | |
id: 10, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return Encoder.encode(d).buffer; | |
}, | |
dec: function (d) { | |
return Decoder.decode(new Uint8Array(d)); | |
}, | |
is: function (d) { | |
return typeof d == "string"; | |
} | |
}, | |
{ | |
name: "ArrayBuffer", | |
id: 11, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return b; | |
}, | |
is: function (d) { | |
return d instanceof ArrayBuffer; | |
} | |
}, | |
{ | |
name: "Int8Array", | |
id: 12, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Int8Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Int8Array; | |
} | |
}, | |
{ | |
name: "Uint8Array", | |
id: 13, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Uint8Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Uint8Array; | |
} | |
}, | |
{ | |
name: "Uint8ClampedArray", | |
id: 14, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Uint8ClampedArray(b); | |
}, | |
is: function (d) { | |
return d instanceof Uint8ClampedArray; | |
} | |
}, | |
{ | |
name: "Int16Array", | |
id: 15, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Int16Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Int16Array; | |
} | |
}, | |
{ | |
name: "Uint16Array", | |
id: 16, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Uint16Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Uint16Array; | |
} | |
}, | |
{ | |
name: "Int32Array", | |
id: 17, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Int32Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Int32Array; | |
} | |
}, | |
{ | |
name: "Uint32Array", | |
id: 18, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Uint32Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Uint32Array; | |
} | |
}, | |
{ | |
name: "Float32Array", | |
id: 19, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Float32Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Float32Array; | |
} | |
}, | |
{ | |
name: "Float64Array", | |
id: 20, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new Float64Array(b); | |
}, | |
is: function (d) { | |
return d instanceof Float64Array; | |
} | |
}, | |
{ | |
name: "BigInt64Array", | |
id: 21, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new BigInt64Array(b); | |
}, | |
is: function (d) { | |
return d instanceof BigInt64Array; | |
} | |
}, | |
{ | |
name: "BigUint64Array", | |
id: 22, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return d.slice(0, d.length).buffer; | |
}, | |
dec: function (b) { | |
return new BigUint64Array(b); | |
}, | |
is: function (d) { | |
return d instanceof BigUint64Array; | |
} | |
}, | |
{ | |
name: "Array", | |
id: 23, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return Array.from(d); | |
}, | |
dec: function (b) { | |
return b; | |
}, | |
is: function (d) { | |
return d instanceof Array; | |
} | |
}, | |
{ | |
name: "Object", | |
id: 24, | |
fixed: false, | |
lbytes: 4, | |
enc: function (d) { | |
return Object.assign({}, d); | |
}, | |
dec: function (b) { | |
return b; | |
}, | |
is: function (d) { | |
return typeof d === "object"; | |
} | |
} | |
]; | |
Nuclei.TYPES = TYPES; | |
var TypesMapId = new Map(); | |
var TypesMapName = new Map(); | |
var TypesTestMapId = new Map(); | |
TYPES.forEach(function (t) { | |
TypesMapId.set(t.id, t); | |
TypesMapName.set(t.name, t); | |
TypesTestMapId.set(t.id, t.is); | |
}); | |
function getTypeIdFromData(data) { | |
for (const [id, is] of TypesTestMapId) { | |
if (is(data)) { return id;} | |
} return 0; | |
} | |
function getTypeFromData(data) { | |
return TypesMapId.get(getTypeIdFromData(data)); | |
} | |
function getTypeFromId (name) { | |
return TypesMapId.get(name); | |
} | |
function getTypeFromName (name) { | |
return TypesMapName.get(name); | |
} | |
var NucleiHeadItem = function NucleiHeadItem( | |
type16b_or_buffer_or_U64_or_uint64, | |
id16b_or_Boffset, | |
offsetB16b_or_Blength, | |
lengthB16b_or_undefined | |
) { | |
if (!(this instanceof NucleiHeadItem)) { | |
return new NucleiHeadItem( | |
type16b_or_buffer_or_U64_or_uint64, | |
id16b_or_Boffset, | |
offsetB16b_or_Blength, | |
lengthB16b_or_undefined | |
); | |
} | |
if (typeof id16b_or_Boffset == "undefined") { | |
this.storage_ = new DataView(new ArrayBuffer(this.BYTES_PER_ELEMENT)); | |
}else if (typeof lengthB16b_or_undefined == "undefined") { | |
this.storage_ = new DataView( | |
type16b_or_buffer_or_U64_or_uint64, | |
id16b_or_Boffset, | |
offsetB16b_or_Blength | |
); | |
} else { | |
this.storage_ = new DataView(new ArrayBuffer(this.BYTES_PER_ELEMENT)); | |
this.storage_.setUint16(0, type16b_or_buffer_or_U64_or_uint64); | |
this.storage_.setUint16(2, id16b_or_Boffset); | |
this.storage_.setUint16(4, offsetB16b_or_Blength); | |
this.storage_.setUint16(6, lengthB16b_or_undefined); | |
} | |
return this; | |
}; | |
NucleiHeadItem.prototype.BYTES_PER_ELEMENT = 8; | |
Object.defineProperty(NucleiHeadItem.prototype, "numeral", { | |
get: function get() { | |
return this.storage_.getBigUint64(0); | |
} | |
}); | |
Object.defineProperty(NucleiHeadItem.prototype, "type", { | |
get: function get() { | |
return this.storage_.getUint16(0); | |
}, | |
set: function set(t) { | |
this.storage_.setUint16(0, t | 0); | |
} | |
}); | |
Object.defineProperty(NucleiHeadItem.prototype, "id", { | |
get: function get() { | |
return this.storage_.getUint16(2); | |
}, | |
set: function set(i) { | |
this.storage_.setUint16(2, i | 0); | |
} | |
}); | |
Object.defineProperty(NucleiHeadItem.prototype, "offset", { | |
get: function get() { | |
return this.storage_.getUint16(4); | |
}, | |
set: function set(o) { | |
this.storage_.setUint16(4, o | 0); | |
} | |
}); | |
Object.defineProperty(NucleiHeadItem.prototype, "length", { | |
get: function get() { | |
return this.storage_.getUint16(6); | |
}, | |
set: function set(l) { | |
this.storage_.setUint16(6, l | 0); | |
} | |
}); | |
Object.defineProperty(NucleiHeadItem.prototype, "copied", { | |
get: function get() { | |
return new NucleiHeadItem(this.type|0, this.id|0, this.offset|0, this.length|0); | |
} | |
}); | |
Nuclei.NucleiHeadItem = NucleiHeadItem; | |
var NucleiHead = function NucleiHead(buffer, byteOffset, byteLength) { | |
if (!(this instanceof NucleiHead)) { | |
return new NucleiHead(buffer, byteOffset, byteLength); | |
} | |
if (typeof buffer == "undefined") { | |
this.storage_ = new DataView(new ArrayBuffer(this.WHOLE_CHUNCK_SIZE_BYTES)); | |
this.count_ = 0; | |
} else { | |
this.storage_ = new DataView(buffer, byteOffset, byteLength); | |
this.count_ = (this.storage_.byteLength - this.storage_.byteOffset - this.HEADER_SIZE_BYTES | 0) / this.ITEM_SIZE_BYTES; | |
} | |
return this; | |
}; | |
NucleiHead.prototype.HEADER_SIZE_BYTES = 4; | |
NucleiHead.prototype.ITEM_SIZE_BYTES = 8; | |
NucleiHead.prototype.ITEM_LENGTH_CHUNCK = 256; | |
NucleiHead.prototype.BODY_CHUNCK_SIZE_BYTES = NucleiHead.prototype.ITEM_SIZE_BYTES * NucleiHead.prototype.ITEM_LENGTH_CHUNCK; | |
NucleiHead.prototype.WHOLE_CHUNCK_SIZE_BYTES = NucleiHead.prototype.HEADER_SIZE_BYTES + NucleiHead.prototype.BODY_CHUNCK_SIZE_BYTES; | |
NucleiHead.prototype.NucleiHeadItem = NucleiHeadItem; | |
Object.defineProperty(NucleiHead.prototype, "buffer", { | |
get: function get() {return this.storage_.buffer;} | |
}); | |
Object.defineProperty(NucleiHead.prototype, "used", { | |
get: function get() {return this.HEADER_SIZE_BYTES + this.ITEM_SIZE_BYTES * this.count_ | 0;} | |
}); | |
Object.defineProperty(NucleiHead.prototype, "available", { | |
get: function get() {return this.storage_.byteLength | 0;} | |
}); | |
Object.defineProperty(NucleiHead.prototype, "free", { | |
get: function get() {return this.available - this.used | 0;} | |
}); | |
Object.defineProperty(NucleiHead.prototype, "clone", { | |
get: function get() { | |
this.storage_.setUint32(0, this.used); | |
return this.storage_.buffer.slice(this.storage_.byteOffset, this.storage_.byteOffset + this.used); | |
} | |
}); | |
Object.defineProperty(NucleiHead.prototype, "at", { | |
get: function get() {return function (index) { | |
return this.NucleiHeadItem(this.storage_.getBigUint64(this.HEADER_SIZE_BYTES + index * this.ITEM_SIZE_BYTES)); | |
};} | |
}); | |
Object.defineProperty(NucleiHead.prototype, "add", { | |
get: function get() { | |
return function (item) { | |
if (this.free < this.ITEM_SIZE_BYTES) { | |
// Increase buffer size | |
var uint8a = new Uint8Array(this.used + this.BODY_CHUNCK_SIZE_BYTES); | |
uint8a.set(new Uint8Array(this.clone), 0); | |
this.storage_ = new DataView(uint8a.buffer); | |
} | |
this.storage_.setBigUint64(this.used, item.numeral); | |
this.count_++; | |
return this.count_-1; | |
}; | |
} | |
}); | |
Nuclei.NucleiHead = NucleiHead; | |
var NucleiNeckItem = function NucleiNeckItem( | |
buffer_or_string, | |
offsetB, | |
lengthB | |
) { | |
if (!(this instanceof NucleiNeckItem)) { | |
return new NucleiNeckItem(buffer_or_string, offsetB, lengthB); | |
} | |
if (!(buffer_or_string instanceof ArrayBuffer)) { | |
this.storage_ = new DataView(this.Encoder.encode(""+buffer_or_string).buffer); | |
} else { | |
this.storage_ = new DataView(buffer_or_string, offsetB, lengthB); | |
} | |
return this; | |
}; | |
NucleiNeckItem.prototype.Encoder = Encoder; | |
NucleiNeckItem.prototype.Decoder = Decoder; | |
Object.defineProperty(NucleiNeckItem.prototype, "used", { | |
get: function get() {return this.storage_.byteLength | 0;} | |
}); | |
Object.defineProperty(NucleiNeckItem.prototype, "clone", { | |
get: function get() {return this.storage_.buffer.slice(this.storage_.byteOffset, this.storage_.byteOffset + this.used);} | |
}); | |
Object.defineProperty(NucleiNeckItem.prototype, "string", { | |
get: function get() {return this.Decoder.decode(new Uint8Array(this.clone));} | |
}); | |
Nuclei.NucleiNeckItem = NucleiNeckItem; | |
var NucleiNeck = function NucleiNeck(buffer, byteOffset, byteLength) { | |
if (!(this instanceof NucleiNeck)) { | |
return new NucleiNeck(buffer, byteOffset, byteLength); | |
} | |
if (typeof buffer == "undefined") { | |
this.storage_ = new DataView(new ArrayBuffer(this.WHOLE_CHUNCK_SIZE_BYTES)); | |
this.offset_bytes_ = this.HEADER_SIZE_BYTES; | |
} else { | |
this.storage_ = new DataView(buffer, byteOffset, byteLength); | |
this.offset_bytes_ = byteLength; | |
} | |
this.storage_uint8_array_ = new Uint8Array(this.storage_.buffer); | |
this.item_ = this.NucleiNeckItem(0); | |
return this; | |
}; | |
NucleiNeck.prototype.TYPE_ID = 255; | |
NucleiNeck.prototype.HEADER_SIZE_BYTES = 4; | |
NucleiNeck.prototype.BODY_CHUNCK_SIZE_BYTES = 256 * 8; | |
NucleiNeck.prototype.WHOLE_CHUNCK_SIZE_BYTES = NucleiNeck.prototype.HEADER_SIZE_BYTES + NucleiNeck.prototype.BODY_CHUNCK_SIZE_BYTES; | |
NucleiNeck.prototype.NucleiNeckItem = NucleiNeckItem; | |
NucleiNeck.prototype.NucleiHeadItem = NucleiHeadItem; | |
Object.defineProperty(NucleiNeck.prototype, "buffer", { | |
get: function get() {return this.storage_.buffer;} | |
}); | |
Object.defineProperty(NucleiNeck.prototype, "used", { | |
get: function get() {return this.offset_bytes_| 0;} | |
}); | |
Object.defineProperty(NucleiNeck.prototype, "available", { | |
get: function get() {return this.storage_.byteLength | 0;} | |
}); | |
Object.defineProperty(NucleiNeck.prototype, "free", { | |
get: function get() {return this.available - this.used | 0;} | |
}); | |
Object.defineProperty(NucleiNeck.prototype, "clone", { | |
get: function get() { | |
this.storage_.setUint32(0, this.used); | |
return this.storage_.buffer.slice(this.storage_.byteOffset, this.storage_.byteOffset + this.used); | |
} | |
}); | |
Object.defineProperty(NucleiNeck.prototype, "retrieve", { | |
get: function get() {return function (header) {return this.NucleiNeckItem(this.buffer, this.storage_.byteOffset + header.offset, header.length);};} | |
}); | |
Object.defineProperty(NucleiNeck.prototype, "append", { | |
get: function get() { | |
return function (string, id) { | |
this.item_ = this.NucleiNeckItem(string); | |
if (this.free < this.item_.used) { | |
// Increase buffer size | |
var uint8a = new Uint8Array(this.used + this.BODY_CHUNCK_SIZE_BYTES); | |
uint8a.set(new Uint8Array(this.clone), 0); | |
this.storage_ = new DataView(uint8a.buffer); | |
this.storage_uint8_array_ = new Uint8Array(this.storage_.buffer); | |
} | |
this.storage_uint8_array_.set(new Uint8Array(this.item_.clone), this.used); | |
this.offset_bytes_ += this.item_.used; | |
return this.NucleiHeadItem(this.TYPE_ID, id, this.offset_bytes_-this.item_.used, this.item_.used); | |
}; | |
} | |
}); | |
Nuclei.NucleiNeck = NucleiNeck; | |
var NucleiBodyItem = function NucleiBodyItem( | |
buffer_or_object, | |
offsetB_or_should_encode_as_less_one, | |
lengthB, | |
type | |
) { | |
if (!(this instanceof NucleiBodyItem)) { | |
return new NucleiBodyItem(buffer_or_object, offsetB_or_should_encode_as_less_one, lengthB, type); | |
} | |
if (!(buffer_or_object instanceof ArrayBuffer) || offsetB_or_should_encode_as_less_one === -1) { | |
this.type_ = this.getTypeIdFromData(buffer_or_object); | |
this.storage_ = new DataView(this.encoders[this.type_].run(buffer_or_object)); | |
} else { | |
this.storage_ = new DataView(buffer_or_object, offsetB_or_should_encode_as_less_one, lengthB); | |
this.type_ = type; | |
} | |
return this; | |
}; | |
NucleiBodyItem.prototype.getTypeIdFromData = getTypeIdFromData; | |
NucleiBodyItem.prototype.encoders = TYPES.map(function (type){return {run: type.enc};}); | |
NucleiBodyItem.prototype.decoders = TYPES.map(function (type){return {run: type.dec} }); | |
Object.defineProperty(NucleiBodyItem.prototype, "buffer", { | |
get: function get() {return this.storage_.buffer;} | |
}); | |
Object.defineProperty(NucleiBodyItem.prototype, "used", { | |
get: function get() {return this.storage_.byteLength | 0;} | |
}); | |
Object.defineProperty(NucleiBodyItem.prototype, "clone", { | |
get: function get() {return this.storage_.buffer.slice(this.storage_.byteOffset, this.storage_.byteOffset + this.used);} | |
}); | |
Object.defineProperty(NucleiBodyItem.prototype, "type", { | |
get: function get() {return this.type_; } | |
}); | |
Object.defineProperty(NucleiBodyItem.prototype, "object", { | |
get: function get() {return this.decoders[this.type_].run(this.clone);} | |
}); | |
Nuclei.NucleiBodyItem = NucleiBodyItem; | |
var NucleiBody = function NucleiBody(buffer, byteOffset, byteLength) { | |
if (!(this instanceof NucleiBody)) { | |
return new NucleiBody(buffer, byteOffset, byteLength); | |
} | |
if (typeof buffer == "undefined") { | |
this.storage_ = new DataView(new ArrayBuffer(this.WHOLE_CHUNCK_SIZE_BYTES)); | |
this.offset_bytes_ = this.HEADER_SIZE_BYTES; | |
} else { | |
this.storage_ = new DataView(buffer, byteOffset, byteLength); | |
this.offset_bytes_ = byteLength; | |
} | |
this.storage_uint8_array_ = new Uint8Array(this.storage_.buffer); | |
this.item_ = this.NucleiBodyItem(0); | |
return this; | |
}; | |
NucleiBody.prototype.HEADER_SIZE_BYTES = 4; | |
NucleiBody.prototype.BODY_CHUNCK_SIZE_BYTES = 256 * 8; | |
NucleiBody.prototype.WHOLE_CHUNCK_SIZE_BYTES = NucleiBody.prototype.HEADER_SIZE_BYTES + NucleiBody.prototype.BODY_CHUNCK_SIZE_BYTES; | |
NucleiBody.prototype.NucleiBodyItem = NucleiBodyItem; | |
NucleiBody.prototype.NucleiHeadItem = NucleiHeadItem; | |
Object.defineProperty(NucleiBody.prototype, "buffer", { | |
get: function get() {return this.storage_.buffer;} | |
}); | |
Object.defineProperty(NucleiBody.prototype, "used", { | |
get: function get() {return this.offset_bytes_| 0;} | |
}); | |
Object.defineProperty(NucleiBody.prototype, "available", { | |
get: function get() {return this.storage_.byteLength | 0;} | |
}); | |
Object.defineProperty(NucleiBody.prototype, "free", { | |
get: function get() {return this.available - this.used | 0;} | |
}); | |
Object.defineProperty(NucleiBody.prototype, "clone", { | |
get: function get() { | |
this.storage_.setUint32(0, this.used); | |
return this.storage_.buffer.slice(this.storage_.byteOffset, this.storage_.byteOffset + this.used); | |
} | |
}); | |
Object.defineProperty(NucleiBody.prototype, "retrieve", { | |
get: function get() {return function (header) {return this.NucleiBodyItem(this.buffer, this.storage_.byteOffset + header.offset, header.length, header.type);};} | |
}); | |
Object.defineProperty(NucleiBody.prototype, "append", { | |
get: function get() { | |
return function (object, id) { | |
this.item_ = this.NucleiBodyItem(object, -1); | |
if (this.free < this.item_.used) { | |
// Increase buffer size | |
var uint8a = new Uint8Array(this.used + this.BODY_CHUNCK_SIZE_BYTES); | |
uint8a.set(new Uint8Array(this.clone), 0); | |
this.storage_ = new DataView(uint8a.buffer); | |
this.storage_uint8_array_ = new Uint8Array(this.storage_.buffer); | |
} | |
this.storage_uint8_array_.set(new Uint8Array(this.item_.clone), this.used); | |
this.offset_bytes_ += this.item_.used; | |
return this.NucleiHeadItem(this.item_.type, id, this.offset_bytes_-this.item_.used, this.item_.used); | |
}; | |
} | |
}); | |
Nuclei.NucleiBody = NucleiBody; | |
var NucleiEncoder = function NucleiEncoder(object) { | |
if (!(this instanceof NucleiEncoder)) { | |
return new NucleiEncoder(object); | |
} | |
// SET BUFFER | |
this.head_ = new NucleiHead(); | |
this.neck_ = new NucleiNeck(); | |
this.body_ = new NucleiBody(); | |
this.input_ = object; | |
this.count_ = 0; | |
return this; | |
}; | |
NucleiEncoder.prototype.NucleiHeadItem = NucleiHeadItem; | |
NucleiEncoder.prototype.getTypeIdFromData = getTypeIdFromData; | |
NucleiEncoder.prototype.NECK_ID = NucleiNeck.prototype.TYPE_ID; | |
NucleiEncoder.prototype.ARRAY_ID = getTypeFromName("Array").id; | |
NucleiEncoder.prototype.OBJECT_ID = getTypeFromName("Object").id; | |
Object.defineProperty(NucleiEncoder.prototype, "head_snapshot", { | |
get: function get() { | |
return this.head_.clone; | |
} | |
}); | |
Object.defineProperty(NucleiEncoder.prototype, "neck_snapshot", { | |
get: function get() { | |
return this.neck_.clone; | |
} | |
}); | |
Object.defineProperty(NucleiEncoder.prototype, "body_snapshot", { | |
get: function get() { | |
return this.body_.clone; | |
} | |
}); | |
Object.defineProperty(NucleiEncoder.prototype, "snapshot", { | |
get: function get() { | |
var head = new Uint8Array(this.head_snapshot); | |
var neck = new Uint8Array(this.neck_snapshot); | |
var body = new Uint8Array(this.body_snapshot); | |
var snapshot = new Uint8Array(head.length + neck.length + body.length); | |
snapshot.set(head, 0); | |
snapshot.set(neck, head.length); | |
snapshot.set(body, head.length + neck.length); | |
return snapshot; | |
} | |
}); | |
Object.defineProperty(NucleiEncoder.prototype, "addBodyItem", { | |
get: function get() { | |
return function (object) { | |
// SET BODY VALUE + STORE RESULTS + SET HEAD VALUE + INCREASE COUNTER | |
this.count_ = this.head_.add(this.body_.append(object, this.count_)); | |
}; | |
} | |
}); | |
Object.defineProperty(NucleiEncoder.prototype, "addNeckItem", { | |
get: function get() { | |
return function (string) { | |
// SET NECK VALUE + STORE RESULTS + SET HEAD VALUE + INCREASE COUNTER | |
this.count_ = this.head_.add(this.neck_.append(string, this.count_)); | |
}; | |
} | |
}); | |
Object.defineProperty(NucleiEncoder.prototype, "addItem", { | |
get: function get() { | |
return function (node) { | |
switch (this.getTypeIdFromData(node)|0) { | |
case this.ARRAY_ID: | |
// SET HEAD VALUE + INCREASE COUNTER | |
this.count_ = this.head_.add(this.NucleiHeadItem(this.ARRAY_ID, this.count_, this.count_, node.length)); | |
for (var i = 0, l = node.length; i < l; i++) { | |
this.addItem(node[i]); | |
} | |
break; | |
case this.OBJECT_ID: | |
// SET HEAD VALUE + INCREASE COUNTER | |
node = Object.entries(node); | |
this.count_ = this.head_.add(this.NucleiHeadItem(this.OBJECT_ID, this.count_, this.count_, node.length*2)); | |
for (var i = 0, l = node.length; i < l; i++) { | |
this.addNeckItem(node[i][0]); | |
this.addItem(node[i][1]); | |
} | |
break; | |
default: | |
this.addBodyItem(node); | |
} | |
}; | |
} | |
}); | |
Nuclei.NucleiEncoder = NucleiEncoder; | |
Object.defineProperty(NucleiEncoder.prototype, "write", { | |
get: function get() { | |
return function () { | |
this.addItem(this.input_); | |
return this; | |
}; | |
} | |
}); | |
var NucleiDecoder = function NucleiDecoder(snapshot) { | |
if (!(this instanceof NucleiDecoder)) { | |
return new NucleiDecoder(snapshot); | |
} | |
// SET BUFFER | |
var dv = new DataView(snapshot.buffer); | |
this.head_ = new NucleiHead(snapshot.buffer, 0, dv.getUint32(0)); | |
this.neck_ = new NucleiNeck( | |
snapshot.buffer, | |
this.head_.used, | |
dv.getUint32( this.head_.used) | |
); | |
this.body_ = new NucleiBody( | |
snapshot.buffer, | |
this.head_.used+this.neck_.used, | |
dv.getUint32( this.head_.used+this.neck_.used) | |
); | |
// SET WORKING VAR | |
this.object_ = {}; | |
this.count_ = 0; | |
return this; | |
}; | |
NucleiDecoder.prototype.NucleiHeadItem = NucleiHeadItem; | |
NucleiDecoder.prototype.NECK_ID = NucleiNeck.prototype.TYPE_ID; | |
NucleiDecoder.prototype.ARRAY_ID = getTypeFromName("Array").id; | |
NucleiDecoder.prototype.OBJECT_ID = getTypeFromName("Object").id; | |
Object.defineProperty(NucleiDecoder.prototype, "readItem", { | |
get: function get() { | |
return function (versatile_head_pointer) { | |
if (typeof versatile_head_pointer == "undefined") {versatile_head_pointer = this.next} | |
switch (versatile_head_pointer.type) { | |
case this.ARRAY_ID: | |
var array = new Array(versatile_head_pointer.length); | |
for (var i = 0, l = array.length; i < l; i++) { | |
array[i] = this.readItem(this.next); | |
} | |
return array; | |
case this.OBJECT_ID: | |
var object = {}; | |
for (var i = 0, l = versatile_head_pointer.length; i < l; i++) { | |
object[this.neck_.retrieve(this.head_.at(this.next).string)] = this.readItem(this.next); | |
} | |
return object; | |
case this.NECK_ID: | |
return this.neck_.retrieve(versatile_head_pointer).string; | |
default: | |
var o = this.body_.retrieve(versatile_head_pointer).object; | |
console.log(o); return o; | |
} | |
}; | |
} | |
}); | |
Object.defineProperty(NucleiDecoder.prototype, "next", { | |
get: function get() { | |
return this.head_.at(this.count_++); | |
} | |
}); | |
Object.defineProperty(NucleiDecoder.prototype, "snapshot", { | |
get: function get() { | |
return this.object_; | |
} | |
}); | |
Object.defineProperty(NucleiDecoder.prototype, "read", { | |
get: function get() { | |
return function () { | |
this.object_ = this.readItem(); | |
return this; | |
}; | |
} | |
}); | |
Nuclei.NucleiDecoder = NucleiDecoder; | |
return Nuclei; | |
})(); | |
window.Nuclei = Nuclei; | |
var encoded = Nuclei.NucleiEncoder({ test: "lol", star: true }).write(); | |
var decoded = Nuclei.NucleiDecoder(encoded.snapshot).read(); | |
console.log(encoded, decoded) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment