2022-09-16 05:58:45 +03:00
|
|
|
import { throwArgumentError, throwError } from "./errors.js";
|
|
|
|
function _getBytes(value, name, copy) {
|
|
|
|
if (value instanceof Uint8Array) {
|
|
|
|
if (copy) {
|
|
|
|
return new Uint8Array(value);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
if (typeof (value) === "string" && value.match(/^0x([0-9a-f][0-9a-f])*$/i)) {
|
|
|
|
const result = new Uint8Array((value.length - 2) / 2);
|
|
|
|
let offset = 2;
|
|
|
|
for (let i = 0; i < result.length; i++) {
|
|
|
|
result[i] = parseInt(value.substring(offset, offset + 2), 16);
|
|
|
|
offset += 2;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return throwArgumentError("invalid BytesLike value", name || "value", value);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get a typed Uint8Array for %%value%%. If already a Uint8Array
|
|
|
|
* the original %%value%% is returned; if a copy is required use
|
|
|
|
* [[getBytesCopy]].
|
|
|
|
*
|
|
|
|
* @see: getBytesCopy
|
|
|
|
*/
|
|
|
|
export function getBytes(value, name) {
|
|
|
|
return _getBytes(value, name, false);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get a typed Uint8Array for %%value%%, creating a copy if necessary
|
|
|
|
* to prevent any modifications of the returned value from being
|
|
|
|
* reflected elsewhere.
|
|
|
|
*
|
|
|
|
* @see: getBytes
|
|
|
|
*/
|
|
|
|
export function getBytesCopy(value, name) {
|
|
|
|
return _getBytes(value, name, true);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Returns true if %%value%% is a valid [[HexString]], with additional
|
|
|
|
* optional constraints depending on %%length%%.
|
|
|
|
*
|
|
|
|
* If %%length%% is //true//, then %%value%% must additionally be a valid
|
|
|
|
* [[HexDataString]] (i.e. even length).
|
|
|
|
*
|
|
|
|
* If %%length%% is //a number//, then %%value%% must represent that many
|
|
|
|
* bytes of data (e.g. ``0x1234`` is 2 bytes).
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function isHexString(value, length) {
|
|
|
|
if (typeof (value) !== "string" || !value.match(/^0x[0-9A-Fa-f]*$/)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (typeof (length) === "number" && value.length !== 2 + 2 * length) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (length === true && (value.length % 2) !== 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Returns true if %%value%% is a valid representation of arbitrary
|
|
|
|
* data (i.e. a valid [[HexDataString]] or a Uint8Array).
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function isBytesLike(value) {
|
|
|
|
return (isHexString(value, true) || (value instanceof Uint8Array));
|
|
|
|
}
|
|
|
|
const HexCharacters = "0123456789abcdef";
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Returns a [[HexDataString]] representation of %%data%%.
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function hexlify(data) {
|
2022-09-16 05:58:45 +03:00
|
|
|
const bytes = getBytes(data);
|
2022-09-05 23:57:11 +03:00
|
|
|
let result = "0x";
|
|
|
|
for (let i = 0; i < bytes.length; i++) {
|
|
|
|
const v = bytes[i];
|
|
|
|
result += HexCharacters[(v & 0xf0) >> 4] + HexCharacters[v & 0x0f];
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Returns a [[HexDataString]] by concatenating all values
|
|
|
|
* within %%data%%.
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function concat(datas) {
|
|
|
|
return "0x" + datas.map((d) => hexlify(d).substring(2)).join("");
|
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Returns the length of %%data%%, in bytes.
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function dataLength(data) {
|
|
|
|
if (isHexString(data, true)) {
|
|
|
|
return (data.length - 2) / 2;
|
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
return getBytes(data).length;
|
2022-09-05 23:57:11 +03:00
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Returns a [[HexDataString]] by slicing %%data%% from the %%start%%
|
|
|
|
* offset to the %%end%% offset.
|
|
|
|
*
|
|
|
|
* By default %%start%% is 0 and %%end%% is the length of %%data%%.
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function dataSlice(data, start, end) {
|
2022-09-16 05:58:45 +03:00
|
|
|
const bytes = getBytes(data);
|
2022-09-05 23:57:11 +03:00
|
|
|
if (end != null && end > bytes.length) {
|
2022-09-16 05:58:45 +03:00
|
|
|
throwError("cannot slice beyond data bounds", "BUFFER_OVERRUN", {
|
2022-09-05 23:57:11 +03:00
|
|
|
buffer: bytes, length: bytes.length, offset: end
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return hexlify(bytes.slice((start == null) ? 0 : start, (end == null) ? bytes.length : end));
|
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Return the [[HexDataString]] result by stripping all **leading**
|
|
|
|
** zero bytes from %%data%%.
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function stripZerosLeft(data) {
|
|
|
|
let bytes = hexlify(data).substring(2);
|
|
|
|
while (bytes.substring(0, 2) == "00") {
|
|
|
|
bytes = bytes.substring(2);
|
|
|
|
}
|
|
|
|
return "0x" + bytes;
|
|
|
|
}
|
|
|
|
function zeroPad(data, length, left) {
|
2022-09-16 05:58:45 +03:00
|
|
|
const bytes = getBytes(data);
|
2022-09-05 23:57:11 +03:00
|
|
|
if (length < bytes.length) {
|
2022-09-16 05:58:45 +03:00
|
|
|
throwError("padding exceeds data length", "BUFFER_OVERRUN", {
|
2022-09-05 23:57:11 +03:00
|
|
|
buffer: new Uint8Array(bytes),
|
|
|
|
length: length,
|
|
|
|
offset: length + 1
|
|
|
|
});
|
|
|
|
}
|
|
|
|
const result = new Uint8Array(length);
|
|
|
|
result.fill(0);
|
|
|
|
if (left) {
|
|
|
|
result.set(bytes, length - bytes.length);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result.set(bytes, 0);
|
|
|
|
}
|
|
|
|
return hexlify(result);
|
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Return the [[HexDataString]] of %%data%% padded on the **left**
|
|
|
|
* to %%length%% bytes.
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function zeroPadValue(data, length) {
|
|
|
|
return zeroPad(data, length, true);
|
|
|
|
}
|
2022-09-16 05:58:45 +03:00
|
|
|
/**
|
|
|
|
* Return the [[HexDataString]] of %%data%% padded on the **right**
|
|
|
|
* to %%length%% bytes.
|
|
|
|
*/
|
2022-09-05 23:57:11 +03:00
|
|
|
export function zeroPadBytes(data, length) {
|
|
|
|
return zeroPad(data, length, false);
|
|
|
|
}
|
|
|
|
//# sourceMappingURL=data.js.map
|