@keeex/utils 7.6.0 → 7.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/array.d.ts CHANGED
@@ -13,6 +13,7 @@
13
13
  * 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.
14
14
  *
15
15
  */
16
+ import type { Arrayable } from "./types/array.js";
16
17
  export type EqualityFunction<T1, T2> = (op1: T1, op2: T2) => boolean;
17
18
  /**
18
19
  * Compare two array-like structure for equal content
@@ -25,6 +26,6 @@ export declare const arrayEqual: <T1 = unknown, T2 = unknown>(op1: ArrayLike<T1>
25
26
  *
26
27
  * @public
27
28
  */
28
- export declare const asArray: <T>(data: Array<T> | (T extends Array<unknown> ? never : T)) => Array<T>;
29
+ export declare const asArray: <T>(data: Arrayable<T>) => Array<T>;
29
30
  /** Return a new array with its string sorted */
30
31
  export declare const toSortedStringArray: (array: Array<string>) => Array<string>;
package/lib/array.js CHANGED
@@ -34,6 +34,6 @@ export const arrayEqual = (op1, op2, eqFunc = useEqOp) => {
34
34
  *
35
35
  * @public
36
36
  */
37
- export const asArray = (data) => Array.isArray(data) ? data : [data];
37
+ export const asArray = (data) => (Array.isArray(data) ? data : [data]);
38
38
  /** Return a new array with its string sorted */
39
39
  export const toSortedStringArray = (array) => array.toSorted(alphaSort);
@@ -17,6 +17,8 @@
17
17
  * Allows returning a promise and resolving it in another scope
18
18
  *
19
19
  * @public
20
+ *
21
+ * @deprecated Use `Promise.withResolvers()`
20
22
  */
21
23
  export declare class DeferredPromise<ResultType> {
22
24
  #private;
@@ -19,6 +19,8 @@
19
19
  * Allows returning a promise and resolving it in another scope
20
20
  *
21
21
  * @public
22
+ *
23
+ * @deprecated Use `Promise.withResolvers()`
22
24
  */
23
25
  export class DeferredPromise {
24
26
  /** The actual promise that can be awaited */
package/lib/bits/hex.d.ts CHANGED
@@ -13,5 +13,12 @@
13
13
  * 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.
14
14
  *
15
15
  */
16
- /** Clean an hex string input; make it even and remove 0x prefix if present */
16
+ /** Remove the 0x prefix if present. */
17
+ export declare const getHexNoPrefix: (input: string) => string;
18
+ /** Ensure that the input is a valid hexadecimal string (only allow `[0-9a-fA-F]`) */
19
+ export declare const isHexString: (input: string) => boolean;
20
+ /**
21
+ * Clean an hex string input; make it even and remove 0x prefix if present.
22
+ * Also convert it to lowercase and check if the input is actually an hexadecimal string.
23
+ */
17
24
  export declare const clearHexInput: (input: string) => string;
package/lib/bits/hex.js CHANGED
@@ -16,15 +16,33 @@
16
16
  const CHARACTER_PER_BYTE = 2;
17
17
  const HEX_PREFIX = "0x";
18
18
  const HEX_PREFIX_LENGTH = HEX_PREFIX.length;
19
- /** Clean an hex string input; make it even and remove 0x prefix if present */
19
+ /** Remove the 0x prefix if present. */
20
+ export const getHexNoPrefix = (input) => input.startsWith(HEX_PREFIX) ? input.substring(HEX_PREFIX_LENGTH) : input;
21
+ const HEX_RANGES_NUMBERS = { min: "0".charCodeAt(0), max: "9".charCodeAt(0) };
22
+ const HEX_RANGES_LOWERCASE = { min: "a".charCodeAt(0), max: "f".charCodeAt(0) };
23
+ const HEX_RANGES_UPPERCASE = { min: "A".charCodeAt(0), max: "F".charCodeAt(0) };
24
+ /** Ensure that the input is a valid hexadecimal string (only allow `[0-9a-fA-F]`) */
25
+ export const isHexString = (input) => {
26
+ for (let i = 0; i < input.length; ++i) {
27
+ const charCode = input.charCodeAt(i);
28
+ if ((charCode < HEX_RANGES_NUMBERS.min || charCode > HEX_RANGES_NUMBERS.max) &&
29
+ (charCode < HEX_RANGES_LOWERCASE.min || charCode > HEX_RANGES_LOWERCASE.max) &&
30
+ (charCode < HEX_RANGES_UPPERCASE.min || charCode > HEX_RANGES_UPPERCASE.max)) {
31
+ return false;
32
+ }
33
+ }
34
+ return true;
35
+ };
36
+ /**
37
+ * Clean an hex string input; make it even and remove 0x prefix if present.
38
+ * Also convert it to lowercase and check if the input is actually an hexadecimal string.
39
+ */
20
40
  export const clearHexInput = (input) => {
21
- const noprefix = !input.startsWith(HEX_PREFIX);
41
+ const withoutPrefix = getHexNoPrefix(input);
42
+ if (!isHexString(withoutPrefix))
43
+ throw new Error("Input is not a valid hexadecimal string");
22
44
  const even = input.length % CHARACTER_PER_BYTE === 0;
23
- if (noprefix && even)
24
- return input;
25
- if (noprefix)
26
- return `0${input}`;
27
45
  if (even)
28
- return input.substring(HEX_PREFIX_LENGTH);
29
- return `0${input.substring(HEX_PREFIX_LENGTH)}`;
46
+ return withoutPrefix.toLowerCase();
47
+ return `0${withoutPrefix.toLowerCase()}`;
30
48
  };
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@keeex/utils","version":"7.6.0","description":"Various utility functions for pure JavaScript","scripts":{},"author":"KeeeX SAS","contributors":[{"name":"Gabriel Paul \"Cley Faye\" Risterucci","email":"gabriel@keeex.net"}],"homepage":"https://keeex.me/oss","keywords":["utility"],"type":"module","license":"MIT","dependencies":{"@keeex/bubble_babble":"^3.0.1","@keeex/log":"^1.7.2","base64-arraybuffer":"^1.0.2","cron-parser":"^5.4.0","ms":"^2.1.3","text-encoding-shim":"^1.0.5"},"exports":{"./array.js":{"node":"./lib/array.js","browser":"./web/array.js","react-native":"./web/array.js","default":"./lib/array.js"},"./arraybuffer.js":{"node":"./lib/arraybuffer.js","browser":"./web/arraybuffer.js","react-native":"./web/arraybuffer.js","default":"./lib/arraybuffer.js"},"./async/asynctrigger.js":{"node":"./lib/async/asynctrigger.js","browser":"./web/async/asynctrigger.js","react-native":"./web/async/asynctrigger.js","default":"./lib/async/asynctrigger.js"},"./async/deferredpromise.js":{"node":"./lib/async/deferredpromise.js","browser":"./web/async/deferredpromise.js","react-native":"./web/async/deferredpromise.js","default":"./lib/async/deferredpromise.js"},"./async/eventqueue.js":{"node":"./lib/async/eventqueue.js","browser":"./web/async/eventqueue.js","react-native":"./web/async/eventqueue.js","default":"./lib/async/eventqueue.js"},"./async/keycache.js":{"node":"./lib/async/keycache.js","browser":"./web/async/keycache.js","react-native":"./web/async/keycache.js","default":"./lib/async/keycache.js"},"./async/queues.js":{"node":"./lib/async/queues.js","browser":"./web/async/queues.js","react-native":"./web/async/queues.js","default":"./lib/async/queues.js"},"./async/timecache.js":{"node":"./lib/async/timecache.js","browser":"./web/async/timecache.js","react-native":"./web/async/timecache.js","default":"./lib/async/timecache.js"},"./base58.js":{"node":"./lib/base58.js","browser":"./web/base58.js","react-native":"./web/base58.js","default":"./lib/base58.js"},"./base64.js":{"node":"./lib/base64.js","browser":"./web/base64.js","react-native":"./web/base64.js","default":"./lib/base64.js"},"./benchmark.js":{"node":"./lib/benchmark.js","browser":"./web/benchmark.js","react-native":"./web/benchmark.js","default":"./lib/benchmark.js"},"./bytebuffer.js":{"node":"./lib/bytebuffer.js","browser":"./web/bytebuffer.js","react-native":"./web/bytebuffer.js","default":"./lib/bytebuffer.js"},"./consts.js":{"node":"./lib/consts.js","browser":"./web/consts.js","react-native":"./web/consts.js","default":"./lib/consts.js"},"./cron.js":{"node":"./lib/cron.js","browser":"./web/cron.js","react-native":"./web/cron.js","default":"./lib/cron.js"},"./dataview.js":{"node":"./lib/dataview.js","browser":"./web/dataview.js","react-native":"./web/dataview.js","default":"./lib/dataview.js"},"./dict.js":{"node":"./lib/dict.js","browser":"./web/dict.js","react-native":"./web/dict.js","default":"./lib/dict.js"},"./error.js":{"node":"./lib/error.js","browser":"./web/error.js","react-native":"./web/error.js","default":"./lib/error.js"},"./global.js":{"node":"./lib/global.js","browser":"./web/global.js","react-native":"./web/global.js","default":"./lib/global.js"},"./hex.js":{"node":"./lib/hex.js","browser":"./web/hex.js","react-native":"./web/hex.js","default":"./lib/hex.js"},"./idx.js":{"node":"./lib/idx.js","browser":"./web/idx.js","react-native":"./web/idx.js","default":"./lib/idx.js"},"./json.js":{"node":"./lib/json.js","browser":"./web/json.js","react-native":"./web/json.js","default":"./lib/json.js"},"./linebuffer.js":{"node":"./lib/linebuffer.js","browser":"./web/linebuffer.js","react-native":"./web/linebuffer.js","default":"./lib/linebuffer.js"},"./marshalling/marshaller.js":{"node":"./lib/marshalling/marshaller.js","browser":"./web/marshalling/marshaller.js","react-native":"./web/marshalling/marshaller.js","default":"./lib/marshalling/marshaller.js"},"./marshalling/unmarshaller.js":{"node":"./lib/marshalling/unmarshaller.js","browser":"./web/marshalling/unmarshaller.js","react-native":"./web/marshalling/unmarshaller.js","default":"./lib/marshalling/unmarshaller.js"},"./number.js":{"node":"./lib/number.js","browser":"./web/number.js","react-native":"./web/number.js","default":"./lib/number.js"},"./path.js":{"node":"./lib/path.js","browser":"./web/path.js","react-native":"./web/path.js","default":"./lib/path.js"},"./promise.js":{"node":"./lib/promise.js","browser":"./web/promise.js","react-native":"./web/promise.js","default":"./lib/promise.js"},"./starttime.js":{"node":"./lib/starttime.js","browser":"./web/starttime.js","react-native":"./web/starttime.js","default":"./lib/starttime.js"},"./string.js":{"node":"./lib/string.js","browser":"./web/string.js","react-native":"./web/string.js","default":"./lib/string.js"},"./triggers.js":{"node":"./lib/triggers.js","browser":"./web/triggers.js","react-native":"./web/triggers.js","default":"./lib/triggers.js"},"./types/array.js":{"node":"./lib/types/array.js","browser":"./web/types/array.js","react-native":"./web/types/array.js","default":"./lib/types/array.js"},"./types/enum.js":{"node":"./lib/types/enum.js","browser":"./web/types/enum.js","react-native":"./web/types/enum.js","default":"./lib/types/enum.js"},"./types/predicateerror.js":{"node":"./lib/types/predicateerror.js","browser":"./web/types/predicateerror.js","react-native":"./web/types/predicateerror.js","default":"./lib/types/predicateerror.js"},"./types/primitive.js":{"node":"./lib/types/primitive.js","browser":"./web/types/primitive.js","react-native":"./web/types/primitive.js","default":"./lib/types/primitive.js"},"./types/record.js":{"node":"./lib/types/record.js","browser":"./web/types/record.js","react-native":"./web/types/record.js","default":"./lib/types/record.js"},"./types/types.js":{"node":"./lib/types/types.js","browser":"./web/types/types.js","react-native":"./web/types/types.js","default":"./lib/types/types.js"},"./types/utils.js":{"node":"./lib/types/utils.js","browser":"./web/types/utils.js","react-native":"./web/types/utils.js","default":"./lib/types/utils.js"},"./uint8array.js":{"node":"./lib/uint8array.js","browser":"./web/uint8array.js","react-native":"./web/uint8array.js","default":"./lib/uint8array.js"},"./units.js":{"node":"./lib/units.js","browser":"./web/units.js","react-native":"./web/units.js","default":"./lib/units.js"}},"files":["/lib","/web"]}
1
+ {"name":"@keeex/utils","version":"7.6.1","description":"Various utility functions for pure JavaScript","scripts":{},"author":"KeeeX SAS","contributors":[{"name":"Gabriel Paul \"Cley Faye\" Risterucci","email":"gabriel@keeex.net"}],"homepage":"https://keeex.me/oss","keywords":["utility"],"type":"module","license":"MIT","dependencies":{"@keeex/bubble_babble":"^3.0.1","@keeex/log":"^1.7.2","base64-arraybuffer":"^1.0.2","cron-parser":"^5.5.0","ms":"^2.1.3","text-encoding-shim":"^1.0.5"},"exports":{"./array.js":{"node":"./lib/array.js","browser":"./web/array.js","react-native":"./web/array.js","default":"./lib/array.js"},"./arraybuffer.js":{"node":"./lib/arraybuffer.js","browser":"./web/arraybuffer.js","react-native":"./web/arraybuffer.js","default":"./lib/arraybuffer.js"},"./async/asynctrigger.js":{"node":"./lib/async/asynctrigger.js","browser":"./web/async/asynctrigger.js","react-native":"./web/async/asynctrigger.js","default":"./lib/async/asynctrigger.js"},"./async/deferredpromise.js":{"node":"./lib/async/deferredpromise.js","browser":"./web/async/deferredpromise.js","react-native":"./web/async/deferredpromise.js","default":"./lib/async/deferredpromise.js"},"./async/eventqueue.js":{"node":"./lib/async/eventqueue.js","browser":"./web/async/eventqueue.js","react-native":"./web/async/eventqueue.js","default":"./lib/async/eventqueue.js"},"./async/keycache.js":{"node":"./lib/async/keycache.js","browser":"./web/async/keycache.js","react-native":"./web/async/keycache.js","default":"./lib/async/keycache.js"},"./async/queues.js":{"node":"./lib/async/queues.js","browser":"./web/async/queues.js","react-native":"./web/async/queues.js","default":"./lib/async/queues.js"},"./async/timecache.js":{"node":"./lib/async/timecache.js","browser":"./web/async/timecache.js","react-native":"./web/async/timecache.js","default":"./lib/async/timecache.js"},"./base58.js":{"node":"./lib/base58.js","browser":"./web/base58.js","react-native":"./web/base58.js","default":"./lib/base58.js"},"./base64.js":{"node":"./lib/base64.js","browser":"./web/base64.js","react-native":"./web/base64.js","default":"./lib/base64.js"},"./benchmark.js":{"node":"./lib/benchmark.js","browser":"./web/benchmark.js","react-native":"./web/benchmark.js","default":"./lib/benchmark.js"},"./bytebuffer.js":{"node":"./lib/bytebuffer.js","browser":"./web/bytebuffer.js","react-native":"./web/bytebuffer.js","default":"./lib/bytebuffer.js"},"./consts.js":{"node":"./lib/consts.js","browser":"./web/consts.js","react-native":"./web/consts.js","default":"./lib/consts.js"},"./cron.js":{"node":"./lib/cron.js","browser":"./web/cron.js","react-native":"./web/cron.js","default":"./lib/cron.js"},"./dataview.js":{"node":"./lib/dataview.js","browser":"./web/dataview.js","react-native":"./web/dataview.js","default":"./lib/dataview.js"},"./dict.js":{"node":"./lib/dict.js","browser":"./web/dict.js","react-native":"./web/dict.js","default":"./lib/dict.js"},"./error.js":{"node":"./lib/error.js","browser":"./web/error.js","react-native":"./web/error.js","default":"./lib/error.js"},"./global.js":{"node":"./lib/global.js","browser":"./web/global.js","react-native":"./web/global.js","default":"./lib/global.js"},"./hex.js":{"node":"./lib/hex.js","browser":"./web/hex.js","react-native":"./web/hex.js","default":"./lib/hex.js"},"./idx.js":{"node":"./lib/idx.js","browser":"./web/idx.js","react-native":"./web/idx.js","default":"./lib/idx.js"},"./json.js":{"node":"./lib/json.js","browser":"./web/json.js","react-native":"./web/json.js","default":"./lib/json.js"},"./linebuffer.js":{"node":"./lib/linebuffer.js","browser":"./web/linebuffer.js","react-native":"./web/linebuffer.js","default":"./lib/linebuffer.js"},"./marshalling/marshaller.js":{"node":"./lib/marshalling/marshaller.js","browser":"./web/marshalling/marshaller.js","react-native":"./web/marshalling/marshaller.js","default":"./lib/marshalling/marshaller.js"},"./marshalling/unmarshaller.js":{"node":"./lib/marshalling/unmarshaller.js","browser":"./web/marshalling/unmarshaller.js","react-native":"./web/marshalling/unmarshaller.js","default":"./lib/marshalling/unmarshaller.js"},"./number.js":{"node":"./lib/number.js","browser":"./web/number.js","react-native":"./web/number.js","default":"./lib/number.js"},"./path.js":{"node":"./lib/path.js","browser":"./web/path.js","react-native":"./web/path.js","default":"./lib/path.js"},"./promise.js":{"node":"./lib/promise.js","browser":"./web/promise.js","react-native":"./web/promise.js","default":"./lib/promise.js"},"./starttime.js":{"node":"./lib/starttime.js","browser":"./web/starttime.js","react-native":"./web/starttime.js","default":"./lib/starttime.js"},"./string.js":{"node":"./lib/string.js","browser":"./web/string.js","react-native":"./web/string.js","default":"./lib/string.js"},"./triggers.js":{"node":"./lib/triggers.js","browser":"./web/triggers.js","react-native":"./web/triggers.js","default":"./lib/triggers.js"},"./types/array.js":{"node":"./lib/types/array.js","browser":"./web/types/array.js","react-native":"./web/types/array.js","default":"./lib/types/array.js"},"./types/enum.js":{"node":"./lib/types/enum.js","browser":"./web/types/enum.js","react-native":"./web/types/enum.js","default":"./lib/types/enum.js"},"./types/predicateerror.js":{"node":"./lib/types/predicateerror.js","browser":"./web/types/predicateerror.js","react-native":"./web/types/predicateerror.js","default":"./lib/types/predicateerror.js"},"./types/primitive.js":{"node":"./lib/types/primitive.js","browser":"./web/types/primitive.js","react-native":"./web/types/primitive.js","default":"./lib/types/primitive.js"},"./types/record.js":{"node":"./lib/types/record.js","browser":"./web/types/record.js","react-native":"./web/types/record.js","default":"./lib/types/record.js"},"./types/types.js":{"node":"./lib/types/types.js","browser":"./web/types/types.js","react-native":"./web/types/types.js","default":"./lib/types/types.js"},"./types/utils.js":{"node":"./lib/types/utils.js","browser":"./web/types/utils.js","react-native":"./web/types/utils.js","default":"./lib/types/utils.js"},"./uint8array.js":{"node":"./lib/uint8array.js","browser":"./web/uint8array.js","react-native":"./web/uint8array.js","default":"./lib/uint8array.js"},"./units.js":{"node":"./lib/units.js","browser":"./web/units.js","react-native":"./web/units.js","default":"./lib/units.js"}},"files":["/lib","/web"]}
package/web/array.d.ts CHANGED
@@ -13,6 +13,7 @@
13
13
  * 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.
14
14
  *
15
15
  */
16
+ import type { Arrayable } from "./types/array.js";
16
17
  export type EqualityFunction<T1, T2> = (op1: T1, op2: T2) => boolean;
17
18
  /**
18
19
  * Compare two array-like structure for equal content
@@ -25,6 +26,6 @@ export declare const arrayEqual: <T1 = unknown, T2 = unknown>(op1: ArrayLike<T1>
25
26
  *
26
27
  * @public
27
28
  */
28
- export declare const asArray: <T>(data: Array<T> | (T extends Array<unknown> ? never : T)) => Array<T>;
29
+ export declare const asArray: <T>(data: Arrayable<T>) => Array<T>;
29
30
  /** Return a new array with its string sorted */
30
31
  export declare const toSortedStringArray: (array: Array<string>) => Array<string>;
@@ -17,6 +17,8 @@
17
17
  * Allows returning a promise and resolving it in another scope
18
18
  *
19
19
  * @public
20
+ *
21
+ * @deprecated Use `Promise.withResolvers()`
20
22
  */
21
23
  export declare class DeferredPromise<ResultType> {
22
24
  #private;
@@ -19,6 +19,8 @@
19
19
  * Allows returning a promise and resolving it in another scope
20
20
  *
21
21
  * @public
22
+ *
23
+ * @deprecated Use `Promise.withResolvers()`
22
24
  */
23
25
  export class DeferredPromise {
24
26
  /** The actual promise that can be awaited */
package/web/bits/hex.d.ts CHANGED
@@ -13,5 +13,12 @@
13
13
  * 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.
14
14
  *
15
15
  */
16
- /** Clean an hex string input; make it even and remove 0x prefix if present */
16
+ /** Remove the 0x prefix if present. */
17
+ export declare const getHexNoPrefix: (input: string) => string;
18
+ /** Ensure that the input is a valid hexadecimal string (only allow `[0-9a-fA-F]`) */
19
+ export declare const isHexString: (input: string) => boolean;
20
+ /**
21
+ * Clean an hex string input; make it even and remove 0x prefix if present.
22
+ * Also convert it to lowercase and check if the input is actually an hexadecimal string.
23
+ */
17
24
  export declare const clearHexInput: (input: string) => string;
package/web/bits/hex.js CHANGED
@@ -16,12 +16,38 @@
16
16
  const CHARACTER_PER_BYTE = 2;
17
17
  const HEX_PREFIX = "0x";
18
18
  const HEX_PREFIX_LENGTH = HEX_PREFIX.length;
19
- /** Clean an hex string input; make it even and remove 0x prefix if present */
19
+ /** Remove the 0x prefix if present. */
20
+ export const getHexNoPrefix = input => input.startsWith(HEX_PREFIX) ? input.substring(HEX_PREFIX_LENGTH) : input;
21
+ const HEX_RANGES_NUMBERS = {
22
+ min: "0".charCodeAt(0),
23
+ max: "9".charCodeAt(0)
24
+ };
25
+ const HEX_RANGES_LOWERCASE = {
26
+ min: "a".charCodeAt(0),
27
+ max: "f".charCodeAt(0)
28
+ };
29
+ const HEX_RANGES_UPPERCASE = {
30
+ min: "A".charCodeAt(0),
31
+ max: "F".charCodeAt(0)
32
+ };
33
+ /** Ensure that the input is a valid hexadecimal string (only allow `[0-9a-fA-F]`) */
34
+ export const isHexString = input => {
35
+ for (let i = 0; i < input.length; ++i) {
36
+ const charCode = input.charCodeAt(i);
37
+ if ((charCode < HEX_RANGES_NUMBERS.min || charCode > HEX_RANGES_NUMBERS.max) && (charCode < HEX_RANGES_LOWERCASE.min || charCode > HEX_RANGES_LOWERCASE.max) && (charCode < HEX_RANGES_UPPERCASE.min || charCode > HEX_RANGES_UPPERCASE.max)) {
38
+ return false;
39
+ }
40
+ }
41
+ return true;
42
+ };
43
+ /**
44
+ * Clean an hex string input; make it even and remove 0x prefix if present.
45
+ * Also convert it to lowercase and check if the input is actually an hexadecimal string.
46
+ */
20
47
  export const clearHexInput = input => {
21
- const noprefix = !input.startsWith(HEX_PREFIX);
48
+ const withoutPrefix = getHexNoPrefix(input);
49
+ if (!isHexString(withoutPrefix)) throw new Error("Input is not a valid hexadecimal string");
22
50
  const even = input.length % CHARACTER_PER_BYTE === 0;
23
- if (noprefix && even) return input;
24
- if (noprefix) return `0${input}`;
25
- if (even) return input.substring(HEX_PREFIX_LENGTH);
26
- return `0${input.substring(HEX_PREFIX_LENGTH)}`;
51
+ if (even) return withoutPrefix.toLowerCase();
52
+ return `0${withoutPrefix.toLowerCase()}`;
27
53
  };