Files
grin-web-wallet/scripts/uuid.js
2024-12-20 18:08:44 -08:00

419 lines
11 KiB
JavaScript
Executable File

// Use strict
"use strict";
// Classes
// UUID class
class Uuid {
// Public
// Constructor
constructor(serializedUuid) {
// Unserialize the serialized UUID
this.unserialize(serializedUuid);
}
// Get version
getVersion() {
// Return version
return this.version;
}
// Get variant
getVariant() {
// Return variant
return this.variant;
}
// Get data
getData() {
// Return data
return this.data;
}
// Serialize
serialize() {
// Return serialized data
return Uuid.serializeData(this.data);
}
// Unserialize
unserialize(serializedUuid) {
// Reset
this.reset();
// Check if the serialized UUID isn't a nil UUID
if(serializedUuid !== Uuid.NIL_SERIALIZED_UUID) {
// Check if serialized UUID isn't formatted correctly
if(Uuid.SERIALIZED_PATTERN.test(serializedUuid) === false) {
// Throw error
throw "Invalid UUID";
}
// Get serialized UUID's version
this.version = parseInt(serializedUuid[Uuid.SERIALIZED_VERSION_OFFSET], Common.HEX_NUMBER_BASE);
// Check if version is invalid
if(this.version < Uuid.MINIMUM_VERSION || this.version > Uuid.MAXIMUM_VERSION) {
// Throw error
throw "Invalid UUID";
}
// Get serialized UUID's variant field
var variantField = parseInt(serializedUuid[Uuid.SERIALIZED_VARIANT_OFFSET], Common.HEX_NUMBER_BASE);
// Check if variant is type zero
if((variantField & Uuid.VARIANT_ZERO_BITMASK) === Uuid.VARIANT_ZERO_BITMASK_RESULT)
// Set variant to variant zero
this.variant = Uuid.VARIANT_ZERO;
// Otherwise check if variant is type one
else if((variantField & Uuid.VARIANT_ONE_BITMASK) === Uuid.VARIANT_ONE_BITMASK_RESULT)
// Set variant to variant one
this.variant = Uuid.VARIANT_ONE;
// Otherwise check if variant is type two
else if((variantField & Uuid.VARIANT_TWO_BITMASK) === Uuid.VARIANT_TWO_BITMASK_RESULT)
// Set variant to variant two
this.variant = Uuid.VARIANT_TWO;
// Otherwise
else {
// Throw error
throw "Invalid UUID";
}
// Set data to serialized UUID's sections as bytes
this.data = Common.fromHexString(serializedUuid.replaceAll(Uuid.SECTION_SEPARATOR, ""));
// Check if variant is two
if(this.getVariant() === Uuid.VARIANT_TWO) {
// Change data's first three components to little endian
this.data.subarray(0, Uint32Array["BYTES_PER_ELEMENT"]).reverse();
this.data.subarray(Uint32Array["BYTES_PER_ELEMENT"], Uint32Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"]).reverse();
this.data.subarray(Uint32Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"], Uint32Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"]).reverse();
}
}
}
// Is random
isRandom() {
// Return if version is four
return this.version === Uuid.VERSION_FOUR;
}
// Random serialized UUID
static randomSerializedUuid() {
// Create a random data
var randomData = new Uint8Array(Uuid.DATA_LENGTH);
// Fill random data with random values
crypto.getRandomValues(randomData);
// Serialize the random data
var serializedRandomData = Uuid.serializeData(randomData);
// Get serialized random data's version
var version = parseInt(serializedRandomData[Uuid.SERIALIZED_VERSION_OFFSET], Common.HEX_NUMBER_BASE);
// Set version to four
version = Uuid.VERSION_FOUR.toString(Common.HEX_NUMBER_BASE);
// Set version in serialized random data
serializedRandomData = serializedRandomData.substring(0, Uuid.SERIALIZED_VERSION_OFFSET) + version + serializedRandomData.substring(Uuid.SERIALIZED_VERSION_OFFSET + version["length"]);
// Get serialized random data's variant
var variant = parseInt(serializedRandomData[Uuid.SERIALIZED_VARIANT_OFFSET], Common.HEX_NUMBER_BASE);
// Set variant to one
variant = ((variant & ~Uuid.VARIANT_ONE_BITMASK) | Uuid.VARIANT_ONE_BITMASK_RESULT).toString(Common.HEX_NUMBER_BASE);
// Set variant in serialized random data
serializedRandomData = serializedRandomData.substring(0, Uuid.SERIALIZED_VARIANT_OFFSET) + variant + serializedRandomData.substring(Uuid.SERIALIZED_VARIANT_OFFSET + variant["length"]);
// Return serialized random data
return serializedRandomData;
}
// Unknown version
static get UNKNOWN_VERSION() {
// Return unknown version
return null;
}
// Unknown variant
static get UNKNOWN_VARIANT() {
// Return unknown variant
return null;
}
// Byte length
static get BYTE_LENGTH() {
// Return byte length
return (Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.THIRD_SECTION_SERIALIZED_LENGTH + Uuid.FOURTH_SECTION_SERIALIZED_LENGTH + Uuid.FIFTH_SECTION_SERIALIZED_LENGTH) / Common.HEX_NUMBER_LENGTH;
}
// Private
// Reset
reset() {
// Set version to unknown
this.version = Uuid.UNKNOWN_VERSION;
// Set variant to unknown
this.variant = Uuid.UNKNOWN_VARIANT;
// Set data
this.data = (new Uint8Array(Uuid.DATA_LENGTH)).fill(0);
}
// Serialize data
static serializeData(data) {
// Copy data
var copy = new Uint8Array(data);
// Get copy's variant field
var variantField = copy[Uuid.DATA_VARIANT_OFFSET] >>> 4;
// Check if variant is type two
if((variantField & Uuid.VARIANT_TWO_BITMASK) === Uuid.VARIANT_TWO_BITMASK_RESULT) {
// Change copy's first three components to big endian
copy.subarray(0, Uint32Array["BYTES_PER_ELEMENT"]).reverse();
copy.subarray(Uint32Array["BYTES_PER_ELEMENT"], Uint32Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"]).reverse();
copy.subarray(Uint32Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"], Uint32Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"] + Uint16Array["BYTES_PER_ELEMENT"]).reverse();
}
// Get copy as a string
var string = Common.toHexString(copy);
// Return string as sections
return string.substring(0, Uuid.FIRST_SECTION_SERIALIZED_LENGTH) + Uuid.SECTION_SEPARATOR + string.substring(Uuid.FIRST_SECTION_SERIALIZED_LENGTH, Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH) + Uuid.SECTION_SEPARATOR + string.substring(Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH, Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.THIRD_SECTION_SERIALIZED_LENGTH) + Uuid.SECTION_SEPARATOR + string.substring(Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.THIRD_SECTION_SERIALIZED_LENGTH, Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.THIRD_SECTION_SERIALIZED_LENGTH + Uuid.FOURTH_SECTION_SERIALIZED_LENGTH) + Uuid.SECTION_SEPARATOR + string.substring(Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.THIRD_SECTION_SERIALIZED_LENGTH + Uuid.FOURTH_SECTION_SERIALIZED_LENGTH, Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.THIRD_SECTION_SERIALIZED_LENGTH + Uuid.FOURTH_SECTION_SERIALIZED_LENGTH + Uuid.FIFTH_SECTION_SERIALIZED_LENGTH);
}
// First section serialized length
static get FIRST_SECTION_SERIALIZED_LENGTH() {
// Return first section serialized length
return 8;
}
// Second section serialized length
static get SECOND_SECTION_SERIALIZED_LENGTH() {
// Return second section serialized length
return 4;
}
// Third section serialized length
static get THIRD_SECTION_SERIALIZED_LENGTH() {
// Return third section serialized length
return 4;
}
// Fourth section serialized length
static get FOURTH_SECTION_SERIALIZED_LENGTH() {
// Return fourth section serialized length
return 4;
}
// Fifth section serialized length
static get FIFTH_SECTION_SERIALIZED_LENGTH() {
// Return fifth section serialized length
return 12;
}
// Section separator
static get SECTION_SEPARATOR() {
// Return section separator
return "-";
}
// Data length
static get DATA_LENGTH() {
// Return data length
return (Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.THIRD_SECTION_SERIALIZED_LENGTH + Uuid.FOURTH_SECTION_SERIALIZED_LENGTH + Uuid.FIFTH_SECTION_SERIALIZED_LENGTH) / Common.HEX_NUMBER_LENGTH;
}
// Data variant offset
static get DATA_VARIANT_OFFSET() {
// Return data variant offset
return 8;
}
// Serialized pattern
static get SERIALIZED_PATTERN() {
// Return serialized pattern
return /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/ui;
}
// Nil serialized UUID
static get NIL_SERIALIZED_UUID() {
// Return nil serialized UUID
return "00000000-0000-0000-0000-000000000000";
}
// Serialized version offset
static get SERIALIZED_VERSION_OFFSET() {
// Return serialized version offset
return Uuid.FIRST_SECTION_SERIALIZED_LENGTH + Uuid.SECTION_SEPARATOR["length"] + Uuid.SECOND_SECTION_SERIALIZED_LENGTH + Uuid.SECTION_SEPARATOR["length"];
}
// Serialized variant offset
static get SERIALIZED_VARIANT_OFFSET() {
// Return serialized variant offset
return Uuid.SERIALIZED_VERSION_OFFSET + Uuid.THIRD_SECTION_SERIALIZED_LENGTH + Uuid.SECTION_SEPARATOR["length"];
}
// Variant zero bitmask
static get VARIANT_ZERO_BITMASK() {
// Return variant zero bitmask
return 0b1000;
}
// Variant zero bitmask result
static get VARIANT_ZERO_BITMASK_RESULT() {
// Return variant zero bitmask result
return 0b0000;
}
// Variant one bitmask
static get VARIANT_ONE_BITMASK() {
// Return variant one bitmask
return 0b1100;
}
// Variant one bitmask result
static get VARIANT_ONE_BITMASK_RESULT() {
// Return variant one bitmask result
return 0b1000;
}
// Variant two bitmask
static get VARIANT_TWO_BITMASK() {
// Return variant two bitmask
return 0b1110;
}
// Variant two bitmask result
static get VARIANT_TWO_BITMASK_RESULT() {
// Return variant two bitmask result
return 0b1100;
}
// Version one
static get VERSION_ONE() {
// Return version one
return 1;
}
// Version two
static get VERSION_TWO() {
// Return version two
return 2;
}
// Version three
static get VERSION_THREE() {
// Return version three
return 3;
}
// Version four
static get VERSION_FOUR() {
// Return version four
return 4;
}
// Version five
static get VERSION_FIVE() {
// Return version five
return 5;
}
// Minimum version
static get MINIMUM_VERSION() {
// Return minimum version
return Uuid.VERSION_ONE;
}
// Maximum version
static get MAXIMUM_VERSION() {
// Return maximum version
return Uuid.VERSION_FIVE;
}
// Variant zero
static get VARIANT_ZERO() {
// Return variant zero
return 0;
}
// Variant one
static get VARIANT_ONE() {
// Return variant one
return 1;
}
// Variant two
static get VARIANT_TWO() {
// Return variant two
return 2;
}
}
// Main function
// Set global object's UUID
globalThis["Uuid"] = Uuid;