@lumjs/encode 2.4.1 → 2.5.0

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/CHANGELOG.md CHANGED
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.5.0] - 2026-02-20
10
+ ### Added
11
+ - A bunch of extra exports that are _module-sets_.
12
+ - `util.bytesToHex()` to be the inverse of `hexToBytes()`.
13
+ - A new `polyfill` sub-module that is not part of the default exports.
14
+ Currently just has polyfills for a few newer Uint8Array methods.
15
+ ### Changed
16
+ - Added options to `util.hexToBytes()` for returning a Uint8Array.
17
+ - Added options to `base64.fromBytes()` and `base64.toBytes()`.
18
+
9
19
  ## [2.4.1] - 2026-02-09
10
20
  ### Changed
11
21
  - Refactored hashifier a bit to make resetting progressive digests simpler.
@@ -96,7 +106,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
96
106
  ### Added
97
107
  - Initial release.
98
108
 
99
- [Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v2.4.1...HEAD
109
+ [Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v2.5.0...HEAD
110
+ [2.5.0]: https://github.com/supernovus/lum.encode.js/compare/v2.4.1...v2.5.0
100
111
  [2.4.1]: https://github.com/supernovus/lum.encode.js/compare/v2.4.0...v2.4.1
101
112
  [2.4.0]: https://github.com/supernovus/lum.encode.js/compare/v2.3.2...v2.4.0
102
113
  [2.3.2]: https://github.com/supernovus/lum.encode.js/compare/v2.3.1...v2.3.2
package/lib/base64.js CHANGED
@@ -67,18 +67,24 @@ function deurlize(string)
67
67
  *
68
68
  * This is a low-level function with minimal options.
69
69
  * See `decodeText()` for a more full-featured function.
70
- *
71
- * This now checks to see if `Uint8Array.fromBase64()` exists,
72
- * and if it does, will use it. Otherwise it uses the original
73
- * encoding algorithm.
74
70
  *
75
- * @param {string} base64 - Base64 encoded-string
76
- * @param {object} [options] Passed to fromBase64() if it exists
71
+ * @param {string} base64 - Base64 encoded-string.
72
+ * @param {object} [options] Options.
73
+ * @param {boolean} [options.native=true] Use fromBase64() if it exists?
74
+ *
75
+ * When enabled, this checks to see if `Uint8Array.fromBase64()` exists,
76
+ * and if it does, will use it, passing the options to it.
77
+ *
78
+ * If this is disabled, the original toBytes algorithm will be used.
79
+ *
80
+ * This option is enabled by default, the only reason I could think of to
81
+ * disable it is if you are using this function as a polyfill.
82
+ *
77
83
  * @returns {Uint8Array}
78
84
  */
79
85
  function toBytes(base64, options={})
80
86
  {
81
- if (UI8_FB64)
87
+ if (UI8_FB64 && (options.native ?? true))
82
88
  {
83
89
  return Uint8Array.fromBase64(base64, options);
84
90
  }
@@ -92,18 +98,24 @@ function toBytes(base64, options={})
92
98
  *
93
99
  * This is a low-level function with no options.
94
100
  * See `encodeText()` for a more full-featured function.
95
- *
96
- * This now checks to see if `bytes.toBase64()` exists,
97
- * and if it does, will use it. Otherwise it uses the original
98
- * decoding algorithm.
99
101
  *
100
- * @param {Uint8Array} bytes - Byte array to convert
101
- * @param {object} [options] Passed to toBase64() if it exists
102
+ * @param {Uint8Array} bytes - Byte array to convert.
103
+ * @param {object} [options] Options.
104
+ * @param {boolean} [options.native=true] Use toBase64() if it exists?
105
+ *
106
+ * When enabled, this checks to see if `bytes.toBase64()` exists,
107
+ * and if it does, will use it, passing the options to it.
108
+ *
109
+ * If this is disabled, the original fromBytes algorithm will be used.
110
+ *
111
+ * This option is enabled by default, the only reason I could think of to
112
+ * disable it is if you are using this function as a polyfill.
113
+ *
102
114
  * @returns {string}
103
115
  */
104
116
  function fromBytes(bytes, options={})
105
117
  {
106
- if (typeof bytes.toBase64 === 'function')
118
+ if ((options.native ?? true) && typeof bytes.toBase64 === 'function')
107
119
  {
108
120
  return bytes.toBase64(options);
109
121
  }
@@ -127,10 +139,11 @@ function fromBytes(bytes, options={})
127
139
  *
128
140
  * If this is a Uint8Array, we can skip the TextEncoder part.
129
141
  *
130
- * @param {(object|boolean)} [options] Options
142
+ * @param {(object|boolean)} [options] Options.
131
143
  *
132
- * - If `boolean`, used as `options.url`
133
- * - Passed to `urlize()` if `options.url` is `true`
144
+ * - If boolean, used as `options.url`.
145
+ * - Passed to urlize() if `options.url` is true.
146
+ * - Always passed to fromBytes().
134
147
  *
135
148
  * @param {boolean} [options.url=false] Urlize the output?
136
149
  * If true, converts `+`, `/`, and `=` to URL-friendly alternatives.
package/lib/hotp.js CHANGED
@@ -27,6 +27,9 @@ function needKey(key) {
27
27
 
28
28
  /**
29
29
  * HMAC-based One-Time-Passwords.
30
+ *
31
+ * TODO: this needs documentation!
32
+ *
30
33
  * @exports module:@lumjs/encode/hotp
31
34
  */
32
35
  class HOTP {
package/lib/index.js CHANGED
@@ -1,5 +1,15 @@
1
1
  /**
2
2
  * A full set of encoding utilities.
3
+ *
4
+ * This module includes alias properties for all sub-modules except `polyfill`.
5
+ *
6
+ * This currently uses lazy-loading for everything other than `util`,
7
+ * but in version 3.0 I will be rewriting this package into ESM format,
8
+ * and the default module will become an alias for the `all` sub-module.
9
+ *
10
+ * I'd suggest using one of the named sub-modules or module-sets if you
11
+ * want to load only specific components.
12
+ *
3
13
  * @module @lumjs/encode
4
14
  */
5
15
 
@@ -7,6 +17,12 @@ const {df,lazy} = require('@lumjs/core');
7
17
  const E = {enumerable: true};
8
18
  const util = require('./util');
9
19
 
20
+ /**
21
+ * @alias module:@lumjs/encode.util
22
+ * @see {@link module:@lumjs/encode/util}
23
+ */
24
+ df(exports, 'Util', {value: util}, E);
25
+
10
26
  /**
11
27
  * @alias module:@lumjs/encode.util
12
28
  * @see {@link module:@lumjs/encode/util}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Some simple polyfills.
3
+ * @module @lumjs/encode/polyfill
4
+ */
5
+ 'use strict';
6
+
7
+ const cp = Object.assign;
8
+ const { isComplex, isObj } = require('@lumjs/core/types');
9
+ const { bytesToHex, hexToBytes } = require('./util.js');
10
+ const { fromBytes: bytesToB64, toBytes: b64ToBytes } = require('./base64.js');
11
+
12
+ const NON = { native: false };
13
+
14
+ /**
15
+ * Polyfills for Uint8Array.
16
+ *
17
+ * This is an array of two ruleset objects:
18
+ *
19
+ * - Uint8Array
20
+ * - fromBase64()
21
+ * - fromHex()
22
+ * - Uint8Array.prototype
23
+ * - toBase64()
24
+ * - toHex()
25
+ *
26
+ * @alias module:@lumjs/encode/polyfill.UI8
27
+ * @type {PolyfillRuleset[]}
28
+ */
29
+ const UI8 = [
30
+ {
31
+ into: Uint8Array,
32
+ fill: {
33
+ fromBase64(string, options) {
34
+ return b64ToBytes(string, cp({}, options, NON));
35
+ },
36
+ fromHex(string) {
37
+ return hexToBytes(string, true, false);
38
+ },
39
+ },
40
+ },
41
+ {
42
+ into: Uint8Array.prototype,
43
+ fill: {
44
+ toBase64(options) {
45
+ return bytesToB64(this, cp({}, options, NON))
46
+ },
47
+ toHex() {
48
+ return bytesToHex(this, false);
49
+ },
50
+ },
51
+ },
52
+ ];
53
+
54
+ const isPolyfill = v => (isObj(v)
55
+ && isComplex(v.into)
56
+ && isObj(v.fill)
57
+ );
58
+
59
+ /**
60
+ * Process one or more polyfill definitions.
61
+ * @param {(PolyfillRuleset|PolyfillRuleset[])} rules - Rulesets to apply.
62
+ *
63
+ * You can pass a single Ruleset object, or an array of associated Rulesets.
64
+ *
65
+ * @returns {Map}
66
+ *
67
+ * @example
68
+ *
69
+ * For these examples I'll be applying the `UI8` polyfills.
70
+ *
71
+ * **Usage if using *ESModules***:
72
+ *
73
+ * ```js
74
+ * import { polyfill, UI8 } from '@lumjs/encode/polyfill';
75
+ * polyfill(UI8);
76
+ * ```
77
+ *
78
+ * **OR if using *CommonJS***:
79
+ *
80
+ * ```js
81
+ * const { polyfill, UI8 } = require('@lumjs/encode/polyfill');
82
+ * polyfill(UI8);
83
+ * ```
84
+ *
85
+ * @alias module:@lumjs/encode/polyfill.polyfill
86
+ */
87
+ function polyfill(rules) {
88
+ let filled = new Map();
89
+
90
+ if (!Array.isArray(rules)) {
91
+ rules = [rules];
92
+ }
93
+
94
+ for (let rule of rules) {
95
+
96
+ if (Array.isArray(rule)) {
97
+ polyfill(...rule);
98
+ continue;
99
+ }
100
+ else if (!isPolyfill(rule)) {
101
+ console.error('invalid polyfill definition', rule);
102
+ continue;
103
+ }
104
+
105
+ let target = rule.into;
106
+ for (let meth in rule.fill) {
107
+ if (target[meth] === undefined) {
108
+ target[meth] = rule.fill[meth];
109
+ }
110
+ }
111
+ }
112
+
113
+ return filled;
114
+ }
115
+
116
+ module.exports = {NON, UI8, isPolyfill, polyfill}
117
+
118
+ /**
119
+ * Polyfill Ruleset
120
+ * @typedef {object} PolyfillRuleset
121
+ *
122
+ * @prop {(object|function)} into - The target to polyfill.
123
+ *
124
+ * Class constructors are functions, class prototypes are objects.
125
+ * Each Ruleset may only have one target, so if you need to polyfill
126
+ * both static and instance methods you'll need to use an array with
127
+ * a Ruleset for the constructor, and a Ruleset for the prototype.
128
+ *
129
+ * @prop {object} fill - An object containing the polyfill methods.
130
+ *
131
+ * Any method in this object that doesn't exist in the `for` target,
132
+ * will be added to it. As these are expected to be methods respecting
133
+ * the `this` context variable they should NOT be arrow (`=>`) closures.
134
+ *
135
+ */
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Make lowercase aliases for every key in an object.
3
+ * @param {object} obj - Target object.
4
+ * @returns {object} `obj`
5
+ */
6
+ function makeSet(obj) {
7
+ for (let key in obj) {
8
+ let lc = key.toLowerCase();
9
+ if (key !== lc) {
10
+ obj[lc] = obj[key];
11
+ }
12
+ }
13
+ return obj;
14
+ }
15
+
16
+ module.exports = {
17
+ makeSet,
18
+ }
@@ -0,0 +1,14 @@
1
+ const { makeSet } = require('./_inc.js');
2
+
3
+ /**
4
+ * A module-set that includes all sub-modules except `polyfill`.
5
+ *
6
+ * More specifically this composes together the `digest` and `otp`
7
+ * module-sets (which in turn compose `base` and `sign` respectively).
8
+ *
9
+ * @alias module:@lumjs/encode/all
10
+ */
11
+ module.exports = makeSet({
12
+ ...(require('./digest')),
13
+ ...(require('./otp')),
14
+ });
@@ -0,0 +1,20 @@
1
+ const { makeSet } = require('./_inc.js');
2
+
3
+ /**
4
+ * A module-set for working with encodings.
5
+ *
6
+ * Includes:
7
+ * - Base32
8
+ * - Base64
9
+ * - Base91
10
+ * - Util
11
+ * As well as lowercase aliases for all of those.
12
+ *
13
+ * @module @lumjs/encode/base
14
+ */
15
+ module.exports = makeSet({
16
+ Base32: require('../base32'),
17
+ Base64: require('../base64'),
18
+ Base91: require('../base91'),
19
+ Util: require('../util'),
20
+ });
@@ -0,0 +1,16 @@
1
+ const { makeSet } = require('./_inc.js');
2
+
3
+ /**
4
+ * A module-set for working with digests (aka data hashes).
5
+ *
6
+ * Includes:
7
+ * - Hash
8
+ * As well as lowercase aliases for all of those,
9
+ * and everything from the `base` set.
10
+ *
11
+ * @module @lumjs/encode/digest
12
+ */
13
+ module.exports = makeSet({
14
+ ...(require('./base.js')),
15
+ Hash: require('../hash.js'),
16
+ });
@@ -0,0 +1,18 @@
1
+ const { makeSet } = require('./_inc.js');
2
+
3
+ /**
4
+ * A module-set for working with One-Time-Passwords (OTP).
5
+ *
6
+ * Includes:
7
+ * - HOTP
8
+ * - TOTP
9
+ * As well as lowercase aliases for all of those,
10
+ * and everything from the `sign` set.
11
+ *
12
+ * @module @lumjs/encode/otp
13
+ */
14
+ module.exports = makeSet({
15
+ ...(require('./sign')),
16
+ HOTP: require('../hotp'),
17
+ TOTP: require('../totp'),
18
+ });
@@ -0,0 +1,20 @@
1
+ const { makeSet } = require('./_inc.js');
2
+
3
+ /**
4
+ * A module-set for working with digital signatures.
5
+ *
6
+ * Includes:
7
+ * - HMAC
8
+ * - PEM
9
+ * - Signature
10
+ * - Util
11
+ * As well as lowercase aliases for all of those.
12
+ *
13
+ * @module @lumjs/encode/sign
14
+ */
15
+ module.exports = makeSet({
16
+ HMAC: require('../hmac.js'),
17
+ PEM: require('../pem.js'),
18
+ Signature: require('../signature.js'),
19
+ Util: require('../util.js'),
20
+ });
package/lib/totp.js CHANGED
@@ -5,6 +5,9 @@ const DEF_OPTS = {step: 30};
5
5
 
6
6
  /**
7
7
  * Time-based One-Time-Passwords.
8
+ *
9
+ * TODO: this needs documentation!
10
+ *
8
11
  * @exports module:@lumjs/encode/totp
9
12
  */
10
13
  class TOTP extends HOTP {
package/lib/util.js CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  const { TypedArray } = require('@lumjs/core/types');
8
8
 
9
+ const UI8_FHEX = (typeof Uint8Array.fromHex === 'function');
10
+
9
11
  /**
10
12
  * Return the ASCII/Unicode number for a character.
11
13
  *
@@ -18,8 +20,7 @@ const { TypedArray } = require('@lumjs/core/types');
18
20
  * @param {string} string
19
21
  * @returns {number}
20
22
  */
21
- exports.ord = function (string)
22
- {
23
+ exports.ord = function (string) {
23
24
  // discuss at: https://locutus.io/php/ord/
24
25
  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
25
26
  // bugfixed by: Onno Marsman
@@ -32,12 +33,10 @@ exports.ord = function (string)
32
33
 
33
34
  var str = string + '',
34
35
  code = str.charCodeAt(0);
35
- if (0xD800 <= code && code <= 0xDBFF)
36
- {
36
+ if (0xD800 <= code && code <= 0xDBFF) {
37
37
  // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
38
38
  var hi = code;
39
- if (str.length === 1)
40
- {
39
+ if (str.length === 1) {
41
40
  // This is just a high surrogate with no following low surrogate, so we return its value;
42
41
  return code;
43
42
  // we could also throw an error as it is not a complete character, but someone may want to know
@@ -45,8 +44,7 @@ exports.ord = function (string)
45
44
  var low = str.charCodeAt(1);
46
45
  return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
47
46
  }
48
- if (0xDC00 <= code && code <= 0xDFFF)
49
- {
47
+ if (0xDC00 <= code && code <= 0xDFFF) {
50
48
  // Low surrogate
51
49
  // This is just a low surrogate with no preceding high surrogate, so we return its value;
52
50
  return code;
@@ -94,67 +92,56 @@ exports.ord = function (string)
94
92
  *
95
93
  * @returns {Array} An array of integers.
96
94
  */
97
- exports.numByteArray = function (numStr, options={})
98
- {
99
- if (typeof options === 'number')
100
- {
101
- options = {size: options};
95
+ exports.numByteArray = function (numStr, options = {}) {
96
+ if (typeof options === 'number') {
97
+ options = { size: options };
102
98
  }
103
99
 
104
- const numOpt = (name, defval, min, max) =>
105
- {
100
+ const numOpt = (name, defval, min, max) => {
106
101
  const optval = options[name];
107
- if (typeof optval !== 'number')
108
- { // Was not a number, skip it.
102
+ if (typeof optval !== 'number') { // Was not a number, skip it.
109
103
  return defval;
110
104
  }
111
- if (optval < min)
112
- { // Value was lower than minimum.
105
+ if (optval < min) { // Value was lower than minimum.
113
106
  throw new RangeError(`${name} value ${optval} is less than ${min}`);
114
107
  }
115
- if (max !== 0 && optval > max)
116
- { // Value was higher than maximum.
108
+ if (max !== 0 && optval > max) { // Value was higher than maximum.
117
109
  throw new RangeError(`${name} value ${optval} is more than ${max}`);
118
110
  }
119
111
 
120
112
  return optval;
121
113
  }
122
114
 
123
- const len = numOpt('size', 2, 1, 0);
115
+ const len = numOpt('size', 2, 1, 0);
124
116
  const base = numOpt('base', 16, 2, 36);
125
117
 
126
118
  let strLen = numStr.length;
127
119
  let remainder = strLen % len;
128
120
 
129
- if (options.strict && remainder !== 0)
130
- {
121
+ if (options.strict && remainder !== 0) {
131
122
  throw new RangeError(`string length ${strLen} is not divisible by ${len}`);
132
123
  }
133
- else if (options.pad && remainder !== 0)
134
- {
124
+ else if (options.pad && remainder !== 0) {
135
125
  const padSize = len - remainder;
136
- numStr = numStr.padStart(strLen+padSize, '0');
126
+ numStr = numStr.padStart(strLen + padSize, '0');
137
127
  strLen = numStr.length;
138
128
  remainder = strLen % len;
139
- if (remainder !== 0)
140
- { // Something is wrong in the universe...
141
- console.error({numStr, strLen, len, remainder, arguments});
129
+ if (remainder !== 0) { // Something is wrong in the universe...
130
+ console.error({ numStr, strLen, len, remainder, arguments });
142
131
  throw new Error("string has remainder after padding");
143
132
  }
144
133
  }
145
134
 
146
- const endOf = strLen - (len-1);
135
+ const endOf = strLen - (len - 1);
147
136
  const bytes = [];
148
137
 
149
- const getBytes = (a,b) => bytes.push(parseInt(numStr.substring(a, b), base));
138
+ const getBytes = (a, b) => bytes.push(parseInt(numStr.substring(a, b), base));
150
139
 
151
- for(let i=0; i < endOf; i+=len)
152
- {
153
- getBytes(i, i+len);
140
+ for (let i = 0; i < endOf; i += len) {
141
+ getBytes(i, i + len);
154
142
  }
155
143
 
156
- if (remainder !== 0)
157
- {
144
+ if (remainder !== 0) {
158
145
  getBytes(strLen - remainder, strLen);
159
146
  }
160
147
 
@@ -167,27 +154,26 @@ exports.numByteArray = function (numStr, options={})
167
154
  * @param {WordArray} wordArray
168
155
  * @returns {Uint8Array}
169
156
  */
170
- exports.wordArrayToUint8Array = function(wordArray)
171
- {
172
- const l = wordArray.sigBytes;
173
- const words = wordArray.words;
174
- const result = new Uint8Array(l);
175
- var i=0 /*dst*/, j=0 /*src*/;
176
- while(true) {
177
- // here i is a multiple of 4
178
- if (i==l)
179
- break;
180
- var w = words[j++];
181
- result[i++] = (w & 0xff000000) >>> 24;
182
- if (i==l)
183
- break;
184
- result[i++] = (w & 0x00ff0000) >>> 16;
185
- if (i==l)
186
- break;
187
- result[i++] = (w & 0x0000ff00) >>> 8;
188
- if (i==l)
189
- break;
190
- result[i++] = (w & 0x000000ff);
157
+ exports.wordArrayToUint8Array = function (wordArray) {
158
+ const l = wordArray.sigBytes;
159
+ const words = wordArray.words;
160
+ const result = new Uint8Array(l);
161
+ var i = 0 /*dst*/, j = 0 /*src*/;
162
+ while (true) {
163
+ // here i is a multiple of 4
164
+ if (i == l)
165
+ break;
166
+ var w = words[j++];
167
+ result[i++] = (w & 0xff000000) >>> 24;
168
+ if (i == l)
169
+ break;
170
+ result[i++] = (w & 0x00ff0000) >>> 16;
171
+ if (i == l)
172
+ break;
173
+ result[i++] = (w & 0x0000ff00) >>> 8;
174
+ if (i == l)
175
+ break;
176
+ result[i++] = (w & 0x000000ff);
191
177
  }
192
178
  return result;
193
179
  }
@@ -199,35 +185,70 @@ exports.wordArrayToUint8Array = function(wordArray)
199
185
  * and was borrowed from the `notp` package.
200
186
  *
201
187
  * @param {Integer} num
202
- * @return {Array} bytes
188
+ * @returns {Array} bytes
203
189
  */
204
- exports.intToBytes = function(num)
205
- {
206
- let bytes = [];
190
+ exports.intToBytes = function (num) {
191
+ let bytes = [];
207
192
 
208
- for(let i=7 ; i>=0 ; --i)
209
- {
210
- bytes[i] = num & (255);
211
- num = num >> 8;
212
- }
193
+ for (let i = 7; i >= 0; --i) {
194
+ bytes[i] = num & (255);
195
+ num = num >> 8;
196
+ }
213
197
 
214
- return bytes;
198
+ return bytes;
215
199
  }
216
200
 
217
201
  /**
218
- * Convert a hex value to a byte array.
202
+ * Convert a hex string to a byte array.
219
203
  *
220
- * Also taken from the `notp` package.
204
+ * Original version was also from the `notp` package,
205
+ * with some of my own enhancements added.
221
206
  *
222
- * @param {String} hex string of hex to convert to a byte array
223
- * @return {Array} bytes
207
+ * @param {string} hex - Hex string to convert to a byte array.
208
+ * @param {boolean} [uint8=false] Return a Uint8Array?
209
+ * @param {boolean} [native=true] Use Uint8Array.fromHex() if it exists?
210
+ *
211
+ * Obviously only applicable if `unit8` is true, this will use the native
212
+ * method if it exists. The only reason I could think of to disable this
213
+ * is if you are using this function as a polyfill.
214
+ *
215
+ * @returns {(number[]|Uint8Array)}
216
+ */
217
+ exports.hexToBytes = function (hex, uint8 = false, native = true) {
218
+
219
+ if (uint8 && native && UI8_FHEX) {
220
+ // A shortcut for modern JS runtimes.
221
+ return Uint8Array.fromHex(hex);
222
+ }
223
+
224
+ let bytes = [];
225
+ for (let c = 0, C = hex.length; c < C; c += 2) {
226
+ bytes.push(parseInt(hex.substring(c, c+2), 16));
227
+ }
228
+ return uint8 ? new Uint8Array(bytes) : bytes;
229
+ }
230
+
231
+ /**
232
+ * Converts a byte array to a hex string.
233
+ *
234
+ * @param {(Uint8Array|number[])} bytes - Byte array.
235
+ * @param {boolean} [native=true] Use bytes.toHex() if it exists?
236
+ *
237
+ * Like the same-named option in hexToBytes, the only reason I could
238
+ * think of to disable this is if you are using this as a polyfill
239
+ * for the `Uint8Array.prototype.toHex` method.
240
+ *
241
+ * @returns {string}
224
242
  */
225
- exports.hexToBytes = function(hex) {
226
- var bytes = [];
227
- for(var c = 0, C = hex.length; c < C; c += 2) {
228
- bytes.push(parseInt(hex.substr(c, 2), 16));
229
- }
230
- return bytes;
243
+ exports.bytesToHex = function (bytes, native = true) {
244
+
245
+ if (native && typeof bytes.toHex === 'function') {
246
+ return bytes.toHex();
247
+ }
248
+
249
+ return Array.from(bytes, function (byte) {
250
+ return ('0' + (byte & 0xFF).toString(16)).slice(-2);
251
+ }).join('');
231
252
  }
232
253
 
233
254
  /**
@@ -248,21 +269,19 @@ exports.hexToBytes = function(hex) {
248
269
  * @returns {TypedArray} Will be an instance of `typeClass`.
249
270
  * @throws {TypeError} If invalid arguments were passed.
250
271
  */
251
- function str2ta(str, typeClass=Uint8Array)
252
- {
272
+ function str2ta(str, typeClass = Uint8Array) {
253
273
  let valid = {
254
274
  str: (typeof str === 'string'),
255
275
  typeClass: (TypedArray.isPrototypeOf(typeClass)),
256
276
  }
257
277
  if (!valid.str || !valid.typeClass) {
258
- console.error('str2ab valid:', valid, 'values: ', {str, typeClass});
278
+ console.error('str2ab valid:', valid, 'values: ', { str, typeClass });
259
279
  throw new TypeError("invalid arguments");
260
280
  }
261
281
 
262
- let buf = new ArrayBuffer(str.length*typeClass.BYTES_PER_ELEMENT);
282
+ let buf = new ArrayBuffer(str.length * typeClass.BYTES_PER_ELEMENT);
263
283
  let bufView = new typeClass(buf);
264
- for (let i = 0, strLen = str.length; i < strLen; i++)
265
- {
284
+ for (let i = 0, strLen = str.length; i < strLen; i++) {
266
285
  bufView[i] = str.charCodeAt(i);
267
286
  }
268
287
 
package/package.json CHANGED
@@ -1,17 +1,23 @@
1
1
  {
2
2
  "name": "@lumjs/encode",
3
- "version": "2.4.1",
3
+ "version": "2.5.0",
4
4
  "main": "lib/index.js",
5
5
  "exports":
6
6
  {
7
7
  ".": "./lib/index.js",
8
+ "./all": "./lib/sets/all.js",
9
+ "./base": "./lib/sets/base.js",
8
10
  "./base32": "./lib/base32.js",
9
11
  "./base64": "./lib/base64.js",
10
12
  "./base91": "./lib/base91.js",
13
+ "./digest": "./lib/sets/digest.js",
11
14
  "./hash": "./lib/hash.js",
12
15
  "./hmac": "./lib/hmac.js",
13
16
  "./hotp": "./lib/hotp.js",
17
+ "./otp": "./lib/sets/otp.js",
14
18
  "./pem": "./lib/pem.js",
19
+ "./polyfill": "./lib/polyfill.js",
20
+ "./sign": "./lib/sets/sign.js",
15
21
  "./signature": "./lib/signature.js",
16
22
  "./totp": "./lib/totp.js",
17
23
  "./util": "./lib/util.js",