1 // ♓🌟 Piscēs ∷ binary.js
2 // ====================================================================
4 // Copyright © 2020–2023 Lady [@ Lady’s Computer].
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
10 import { fill
, map
, reduce
} from "./collection.js";
11 import { bind
, call
} from "./function.js";
12 import { ceil
, floor
} from "./numeric.js";
13 import { hasOwnProperty
, objectCreate
} from "./object.js";
20 import { ITERATOR
} from "./value.js";
22 const Buffer
= ArrayBuffer
;
23 const View
= DataView
;
24 const TypedArray
= Object
.getPrototypeOf(Uint8Array
);
25 const { prototype: arrayPrototype
} = Array
;
26 const { prototype: bufferPrototype
} = Buffer
;
27 const { prototype: sharedBufferPrototype
} = SharedArrayBuffer
;
28 const { prototype: rePrototype
} = RegExp
;
29 const { prototype: typedArrayPrototype
} = TypedArray
;
30 const { prototype: viewPrototype
} = View
;
32 const { [ITERATOR
]: arrayIterator
} = arrayPrototype
;
34 next
: arrayIteratorNext
,
35 } = Object
.getPrototypeOf([][ITERATOR
]());
36 const argumentIterablePrototype
= {
41 call(arrayIterator
, this.args
, []),
47 const binaryCodeUnitIterablePrototype
= {
52 call(arrayIterator
, this, []),
59 const { exec
: reExec
} = rePrototype
;
60 const getBufferByteLength
=
61 Object
.getOwnPropertyDescriptor(bufferPrototype
, "byteLength").get;
62 const getSharedBufferByteLength
=
63 Object
.getOwnPropertyDescriptor(sharedBufferPrototype
, "byteLength")
65 const getTypedArrayBuffer
=
66 Object
.getOwnPropertyDescriptor(typedArrayPrototype
, "buffer").get;
67 const getTypedArrayByteLength
=
68 Object
.getOwnPropertyDescriptor(typedArrayPrototype
, "byteLength")
70 const getTypedArrayByteOffset
=
71 Object
.getOwnPropertyDescriptor(typedArrayPrototype
, "byteOffset")
74 Object
.getOwnPropertyDescriptor(viewPrototype
, "buffer").get;
75 const getViewByteLength
=
76 Object
.getOwnPropertyDescriptor(viewPrototype
, "byteLength").get;
77 const getViewByteOffset
=
78 Object
.getOwnPropertyDescriptor(viewPrototype
, "byteOffset").get;
80 getUint8
: viewGetUint8
,
81 setUint8
: viewSetUint8
,
82 setUint16
: viewSetUint16
,
86 * Returns an ArrayBuffer for encoding generated from the provided
89 const bufferFromArgs
= ($, $s
) => {
91 // Try just getting the array buffer associated with the first
92 // argument and returning it if possible.
93 return toArrayBuffer($);
95 // There is no array buffer associated with the first argument.
97 // Construct a string and convert it to an array buffer instead.
103 (result
, ucsCharacter
, index
) => (
104 call(viewSetUint16
, result
, [
106 getCodeUnit(ucsCharacter
, 0),
109 new View(new Buffer(string
.length
* 2)),
113 typeof $ === "string"
115 : hasOwnProperty($, "raw")
118 ...objectCreate(argumentIterablePrototype
, {
128 * Returns the result of decoding the provided base16 string into an
131 * ※ This function is not exposed.
133 const decodeBase16
= (source
) => {
137 const code
= getCodeUnit(ucsCharacter
, 0);
138 const result
= code
>= 0x30 && code
<= 0x39
140 : code
>= 0x41 && code
<= 0x46
142 : code
>= 0x61 && code
<= 0x66
146 // The source contains an invalid character.
147 throw new RangeError(
148 `Piscēs: Invalid character in Base64: ${ucsCharacter}.`,
151 // The source contains a valid character with a recognized
157 const { length
} = u4s
;
158 if (length
% 2 === 1) {
159 // The length is such that an entire letter would be dropped during
160 // a forgiving decode.
161 throw new RangeError(
162 `Piscēs: Base16 string has invalid length: ${source}.`,
165 // Every letter contributes at least some bits to the result.
166 const dataView
= new View(new Buffer(floor(length
/ 2)));
167 for (let index
= 0; index
< length
- 1;) {
168 // Iterate over the characters and assign their bits to the
170 call(viewSetUint8
, dataView
, [
172 (u4s
[index
] << 4) | u4s
[++index
, index
++],
175 return call(getViewBuffer
, dataView
, []);
180 * Returns the result of decoding the provided base32 string into an
183 * If the second argument is truthy, uses Crockford’s encoding rather
184 * than the RFC’s (see <https://www.crockford.com/base32.html>). This
185 * is more human‐friendly and tolerant. Check digits are not supported.
187 * ※ This function is not exposed.
189 const decodeBase32
= (source
, wrmg
) => {
192 ? stringReplace(source
, /-/gu
, "")
193 : source
.length
% 8 === 0
194 ? stringReplace(source
, /(?:=|={3,4}|={6})$/u, "")
197 const code
= getCodeUnit(ucsCharacter
, 0);
199 ? code
>= 0x30 && code
<= 0x39
201 : code
>= 0x41 && code
<= 0x48
205 : code
>= 0x4A && code
<= 0x4B
209 : code
>= 0x4D && code
<= 0x4E
213 : code
>= 0x50 && code
<= 0x54
216 : code
>= 0x56 && code
<= 0x5A
218 : code
>= 0x61 && code
<= 0x68
222 : code
>= 0x6A && code
<= 0x6B
226 : code
>= 0x6D && code
<= 0x6E
230 : code
>= 0x70 && code
<= 0x74
233 : code
>= 0x76 && code
<= 0x7A
236 : code
>= 0x41 && code
<= 0x5A
238 : code
>= 0x61 && code
<= 0x7A
239 ? code
- 97 // same result as above; case insensitive
240 : code
>= 0x32 && code
<= 0x37
241 ? code
- 24 // digits 2–7 map to 26–31
244 // The source contains an invalid character.
245 throw new RangeError(
246 `Piscēs: Invalid character in Base32: ${ucsCharacter}.`,
249 // The source contains a valid character with a recognized
255 const { length
} = u5s
;
256 const lengthMod8
= length
% 8;
257 if (lengthMod8
=== 1 || lengthMod8
=== 3 || lengthMod8
=== 6) {
258 // The length is such that an entire letter would be dropped during
259 // a forgiving decode.
260 throw new RangeError(
261 `Piscēs: Base32 string has invalid length: ${source}.`,
264 // Every letter contributes at least some bits to the result.
265 const dataView
= new View(new Buffer(floor(length
* 5 / 8)));
266 for (let index
= 0; index
< length
- 1;) {
267 // Iterate over the characters and assign their bits to the
270 // The final index is not handled; if the string is not divisible
271 // by 8, some bits might be dropped. This matches the “forgiving
272 // decode” behaviour specified by WhatW·G for base64.
273 const dataIndex
= ceil(index
* 5 / 8);
274 const remainder
= index
% 8;
275 call(viewSetUint8
, dataView
, [
278 ? u5s
[index
] << 3 | u5s
[++index
] >> 2
280 ? u5s
[index
] << 6 | u5s
[++index
] << 1 | u5s
[++index
] >> 4
282 ? u5s
[index
] << 4 | u5s
[++index
] >> 1
284 ? u5s
[index
] << 7 | u5s
[++index
] << 2 | u5s
[++index
] >> 3
285 : u5s
[index
] << 5 | u5s
[++index
, index
++], // remainder === 6
288 return call(getViewBuffer
, dataView
, []);
293 * Returns the result of decoding the provided base64 string into an
296 * ※ This function is not exposed.
298 const decodeBase64
= (source
, safe
= false) => {
300 source
.length
% 4 === 0
301 ? stringReplace(source
, /={1,2}$/u, "")
304 const code
= getCodeUnit(ucsCharacter
, 0);
305 const result
= code
>= 0x41 && code
<= 0x5A
307 : code
>= 0x61 && code
<= 0x7A
309 : code
>= 0x30 && code
<= 0x39
311 : code
=== (safe
? 0x2D : 0x2B)
313 : code
=== (safe
? 0x5F : 0x2F)
317 // The source contains an invalid character.
318 throw new RangeError(
319 `Piscēs: Invalid character in Base64: ${ucsCharacter}.`,
322 // The source contains a valid character with a recognized
328 const { length
} = u6s
;
329 if (length
% 4 === 1) {
330 // The length is such that an entire letter would be dropped during
331 // a forgiving decode.
332 throw new RangeError(
333 `Piscēs: Base64 string has invalid length: ${source}.`,
336 // Every letter contributes at least some bits to the result.
337 const dataView
= new View(new Buffer(floor(length
* 3 / 4)));
338 for (let index
= 0; index
< length
- 1;) {
339 // Iterate over the characters and assign their bits to the
342 // The final index is not handled; if the string is not divisible
343 // by 4, some bits might be dropped. This matches the “forgiving
344 // decode” behaviour specified by WhatW·G for base64.
345 const dataIndex
= ceil(index
* 3 / 4);
346 const remainder
= index
% 4;
347 call(viewSetUint8
, dataView
, [
350 ? u6s
[index
] << 2 | u6s
[++index
] >> 4
352 ? u6s
[index
] << 4 | u6s
[++index
] >> 2
353 : u6s
[index
] << 6 | u6s
[++index
, index
++], // remainder === 2
356 return call(getViewBuffer
, dataView
, []);
361 * Returns the result of encoding the provided ArrayBuffer into a
364 * ※ This function is not exposed.
366 const encodeBase16
= (buffer
) => {
367 const dataView
= new View(buffer
);
368 const byteLength
= call(getBufferByteLength
, buffer
, []);
369 const minimumLengthOfResults
= byteLength
* 2;
370 const resultingCodeUnits
= fill(
372 binaryCodeUnitIterablePrototype
,
373 { length
: { value
: minimumLengthOfResults
} },
377 for (let index
= 0; index
< byteLength
;) {
378 // Iterate over the bytes and generate code units for them.
379 const codeUnitIndex
= index
* 2;
380 const datum
= call(viewGetUint8
, dataView
, [index
++]);
381 const u4s
= [datum
>> 4, datum
& 0xF];
382 for (let u4i
= 0; u4i
< 2; ++u4i
) {
383 // Handle the high four bits, then the low four bits.
385 const result
= u4
< 10 ? u4
+ 48 : u4
< 16 ? u4
+ 55 : -1;
387 // No mapping exists for these four bits.
389 // ※ This shouldn’t be possible!
390 throw new RangeError(
391 `Piscēs: Unexpected Base16 value: ${u4}.`,
394 // A mapping exists for the bits.
395 resultingCodeUnits
[codeUnitIndex
+ u4i
] = result
;
399 return stringFromCodeUnits(...resultingCodeUnits
);
403 * Returns the result of encoding the provided ArrayBuffer into a
406 * ※ This function is not exposed.
408 const encodeBase32
= (buffer
, wrmg
= false) => {
409 const dataView
= new View(buffer
);
410 const byteLength
= call(getBufferByteLength
, buffer
, []);
411 const minimumLengthOfResults
= ceil(byteLength
* 8 / 5);
412 const fillByte
= wrmg
? 0x2D : 0x3D;
413 const resultingCodeUnits
= fill(
415 binaryCodeUnitIterablePrototype
,
418 value
: minimumLengthOfResults
+
419 (8 - (minimumLengthOfResults
% 8)) % 8,
425 for (let index
= 0; index
< byteLength
;) {
426 // Iterate over the bytes and generate code units for them.
427 const codeUnitIndex
= ceil(index
* 8 / 5);
428 const currentIndex
= codeUnitIndex
+ +(
429 0b01011 & 1 << index
% 5 &&
430 resultingCodeUnits
[codeUnitIndex
] != fillByte
431 ); // bytes 0, 1 & 3 handle two letters; this is for the second
432 const remainder
= currentIndex
% 8;
433 const currentByte
= call(viewGetUint8
, dataView
, [index
]);
435 0b01011010 & 1 << remainder
&& ++index
< byteLength
436 // digits 1, 3, 4 & 6 span multiple bytes
437 ? call(viewGetUint8
, dataView
, [index
])
439 const u5
= remainder
=== 0
442 ? (currentByte
& 0b00000111) << 2 | nextByte
>> 6
444 ? (currentByte
& 0b00111111) >> 1
446 ? (currentByte
& 0b00000001) << 4 | nextByte
>> 4
448 ? (currentByte
& 0b00001111) << 1 | nextByte
>> 7
450 ? (currentByte
& 0b01111111) >> 2
452 ? (currentByte
& 0b00000011) << 3 | nextByte
>> 5
453 : (++index
, currentByte
& 0b00011111); // remainder === 7
455 ? u5
< 10 ? u5
+ 48 : u5
< 18
476 // No mapping exists for these five bits.
478 // ※ This shouldn’t be possible!
479 throw new RangeError(`Piscēs: Unexpected Base32 value: ${u5}.`);
481 // A mapping exists for the bits.
482 resultingCodeUnits
[currentIndex
] = result
;
485 const answer
= stringFromCodeUnits(...resultingCodeUnits
);
486 return wrmg
? answer
.replace(/-+$/u, "") : answer
;
490 * Returns the result of encoding the provided ArrayBuffer into a
493 * ※ This function is not exposed.
495 const encodeBase64
= (buffer
, safe
= false) => {
496 const dataView
= new View(buffer
);
497 const byteLength
= call(getBufferByteLength
, buffer
, []);
498 const minimumLengthOfResults
= ceil(byteLength
* 4 / 3);
499 const resultingCodeUnits
= fill(
501 binaryCodeUnitIterablePrototype
,
504 value
: minimumLengthOfResults
+
505 (4 - (minimumLengthOfResults
% 4)) % 4,
511 for (let index
= 0; index
< byteLength
;) {
512 // Iterate over the bytes and generate code units for them.
513 const codeUnitIndex
= ceil(index
* 4 / 3);
514 const currentIndex
= codeUnitIndex
+ +(
515 index
% 3 === 0 && resultingCodeUnits
[codeUnitIndex
] != 0x3D
516 ); // every third byte handles two letters; this is for the second
517 const remainder
= currentIndex
% 4;
518 const currentByte
= call(viewGetUint8
, dataView
, [index
]);
519 const nextByte
= remainder
% 3 && ++index
< byteLength
520 // digits 1 & 2 span multiple bytes
521 ? call(viewGetUint8
, dataView
, [index
])
523 const u6
= remainder
=== 0
526 ? (currentByte
& 0b00000011) << 4 | nextByte
>> 4
528 ? (currentByte
& 0b00001111) << 2 | nextByte
>> 6
529 : (++index
, currentByte
& 0b00111111); // remainder === 3
530 const result
= u6
< 26
537 ? (safe
? 0x2D : 0x2B)
539 ? (safe
? 0x5F : 0x2F)
542 // No mapping exists for these six bits.
544 // ※ This shouldn’t be possible!
545 throw new RangeError(`Piscēs: Unexpected Base64 value: ${u6}.`);
547 // A mapping exists for the bits.
548 resultingCodeUnits
[currentIndex
] = result
;
551 return stringFromCodeUnits(...resultingCodeUnits
);
555 * Returns a source string generated from the arguments passed to a
558 * ※ This function is not exposed.
560 const sourceFromArgs
= ($, $s
) =>
562 typeof $ === "string" ? $ : hasOwnProperty($, "raw")
565 ...objectCreate(argumentIterablePrototype
, {
575 * Returns an ArrayBuffer generated from the provided base16 string.
577 * This function can also be used as a tag for a template literal. The
578 * literal will be interpreted akin to `String.raw`.
580 * ☡ This function throws if the provided string is not a valid base16
583 export const base16Binary
= ($, ...$s
) =>
584 decodeBase16(sourceFromArgs($, $s
));
587 * Returns a (big‐endian) base16 string created from the provided typed
588 * array, buffer, or (16‐bit) string.
590 * This function can also be used as a tag for a template literal. The
591 * literal will be interpreted akin to `String.raw`.
593 export const base16String
= ($, ...$s
) =>
594 encodeBase16(bufferFromArgs($, $s
));
597 * Returns an ArrayBuffer generated from the provided base32 string.
599 * This function can also be used as a tag for a template literal. The
600 * literal will be interpreted akin to `String.raw`.
602 * ☡ This function throws if the provided string is not a valid base32
605 export const base32Binary
= ($, ...$s
) =>
606 decodeBase32(sourceFromArgs($, $s
));
609 * Returns a (big‐endian) base32 string created from the provided typed
610 * array, buffer, or (16‐bit) string.
612 * This function can also be used as a tag for a template literal. The
613 * literal will be interpreted akin to `String.raw`.
615 export const base32String
= ($, ...$s
) =>
616 encodeBase32(bufferFromArgs($, $s
));
619 * Returns an ArrayBuffer generated from the provided base64 string.
621 * This function can also be used as a tag for a template literal. The
622 * literal will be interpreted akin to `String.raw`.
624 * ☡ This function throws if the provided string is not a valid base64
627 export const base64Binary
= ($, ...$s
) =>
628 decodeBase64(sourceFromArgs($, $s
));
631 * Returns a (big‐endian) base64 string created from the provided typed
632 * array, buffer, or (16‐bit) string.
634 * This function can also be used as a tag for a template literal. The
635 * literal will be interpreted akin to `String.raw`.
637 export const base64String
= ($, ...$s
) =>
638 encodeBase64(bufferFromArgs($, $s
));
641 * Returns an ArrayBuffer generated from the provided filename‐safe
644 * This function can also be used as a tag for a template literal. The
645 * literal will be interpreted akin to `String.raw`.
647 * ☡ This function throws if the provided string is not a valid
648 * filename‐safe base64 string.
650 export const filenameSafeBase64Binary
= ($, ...$s
) =>
651 decodeBase64(sourceFromArgs($, $s
), true);
654 * Returns a (big‐endian) filename‐safe base64 string created from the
655 * provided typed array, buffer, or (16‐bit) string.
657 * This function can also be used as a tag for a template literal. The
658 * literal will be interpreted akin to `String.raw`.
660 export const filenameSafeBase64String
= ($, ...$s
) =>
661 encodeBase64(bufferFromArgs($, $s
), true);
664 * Returns the byte length for the provided array buffer or array
667 * ☡ This function throws if the provided value is not an array buffer,
668 * data view, or typed array.
670 export const getByteLength
= ($) => {
672 // Attempt to get the byte length from the provided value as an
674 return call(getBufferByteLength
, $, []);
676 // The provided value is not an `ArrayBuffer`.
680 // Attempt to get the byte length from the provided value as a
681 // `SharedArrayBuffer`.
682 return call(getSharedBufferByteLength
, $, []);
684 // The provided value is not a `SharedArrayBuffer`.
688 // Attempt to get the byte length from the provided value as a
690 return call(getViewByteLength
, $, []);
692 // The provided value is not a data view.
696 // Attempt to get the byte length from the provided value as a
698 return call(getTypedArrayByteLength
, $, []);
700 // The provided value is not a typed array.
703 throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`);
707 * Returns the byte offset for the provided array buffer or array
710 * ※ This function always returns `0` for array buffers.
712 * ☡ This function throws if the provided value is not an array buffer,
713 * data view, or typed array.
715 export const getByteOffset
= ($) => {
716 if (isArrayBuffer($)) {
717 // The provided value is an array buffer.
721 // Attempt to get the byte offset from the provided value as a
723 return call(getViewByteOffset
, $, []);
725 // The provided value is not a data view.
729 // Attempt to get the byte offset from the provided value as a
731 return call(getTypedArrayByteOffset
, $, []);
733 // The provided value is not a typed array.
736 throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`);
741 * Returns whether the provided value is a view on an underlying array
744 * ※ This function returns true for typed arrays and data views.
746 export const { isView
: isArrayBufferView
} = Buffer
;
749 * Returns whether the provided value is an array buffer.
751 * ※ This function returns true for both `ArrayBuffer`s and
752 * `SharedArrayBuffer`s.
754 export const isArrayBuffer
= ($) => {
756 // Try to see if the provided argument has array buffer internal
757 // slots and return true if so.
758 return call(getBufferByteLength
, $, []), true;
760 // The provided argument does not have array buffer internal slots.
764 // Try to see if the provided argument has array buffer internal
765 // slots and return true if so.
766 return call(getSharedBufferByteLength
, $, []), true;
768 // The provided argument does not have array buffer internal slots.
775 * Returns whether the provided value is a base16 string.
777 * ※ This function returns false if the provided value is not a string
780 export const isBase16
= ($) => {
781 if (typeof $ !== "string") {
782 // The provided value is not a string.
785 // The provided value is a string.
786 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
787 return source
.length
% 2 !== 1 &&
788 call(reExec
, /[^0-9A-F]/iu, [source
]) === null;
793 * Returns whether the provided value is a base32 string.
795 * ※ This function returns false if the provided value is not a string
798 export const isBase32
= ($) => {
799 if (typeof $ !== "string") {
800 // The provided value is not a string.
803 // The provided value is a string.
804 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
805 const trimmed
= source
.length
% 8 === 0
806 ? stringReplace(source
, /(?:=|={3,4}|={6})$/u, "")
808 return trimmed
.length
% 8 !== 1 &&
809 call(reExec
, /[^2-7A-Z/]/iu
, [trimmed
]) === null;
814 * Returns whether the provided value is a Base64 string.
816 * ※ This function returns false if the provided value is not a string
819 export const isBase64
= ($) => {
820 if (typeof $ !== "string") {
821 // The provided value is not a string.
824 // The provided value is a string.
825 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
826 const trimmed
= source
.length
% 4 === 0
827 ? stringReplace(source
, /={1,2}$/u, "")
829 return trimmed
.length
% 4 !== 1 &&
830 call(reExec
, /[^0-9A-Za-z+\/]/u, [trimmed
]) === null;
835 * Returns whether the provided value is a filename‐safe base64 string.
837 * ※ This function returns false if the provided value is not a string
840 export const isFilenameSafeBase64
= ($) => {
841 if (typeof $ !== "string") {
842 // The provided value is not a string.
845 // The provided value is a string.
846 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
847 const trimmed
= source
.length
% 4 === 0
848 ? stringReplace(source
, /={1,2}$/u, "")
850 return trimmed
.length
% 4 !== 1 &&
851 call(reExec
, /[^0-9A-Za-z_-]/u, [trimmed
]) === null;
855 /** Returns whether the provided value is a shared array buffer. */
856 export const isSharedArrayBuffer
= ($) => {
858 // Try to see if the provided argument has shared array buffer
859 // internal slots and return true if so.
860 return call(getSharedBufferByteLength
, $, []), true;
862 // The provided argument does not have data view internal slots.
867 /** Returns whether the provided value is a typed array. */
868 export const isTypedArray
= ($) => {
870 // Try to see if the provided argument has typed array internal
871 // slots and return true if so.
872 return call(getTypedArrayBuffer
, $, []), true;
874 // The provided argument does not have typed array internal slots.
880 * Returns whether the provided value is a W·R·M·G (Crockford) base32
881 * string. Check digits are not supported.
883 * ※ This function returns false if the provided value is not a string
886 export const isWRMGBase32
= ($) => {
887 if (typeof $ !== "string") {
888 // The provided value is not a string.
891 // The provided value is a string.
892 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
893 const trimmed
= stringReplace(source
, /-/gu
, "");
894 return trimmed
.length
% 8 !== 1 &&
895 call(reExec
, /[^0-9A-TV-Z]/iu, [trimmed
]) === null;
900 * Returns the array buffer associated with the provided object.
902 * ☡ This function throws if the provided object is not a data view or
905 export const toArrayBuffer
= ($) => {
906 if (isArrayBuffer($)) {
907 // The provided argument has array buffer internal slots.
910 // The provided argument does not have array buffer internal slots.
912 // The provided argument has typed array internal slots.
913 return call(getTypedArrayBuffer
, $, []);
918 // The provided argument has data view internal slots.
919 return call(getViewBuffer
, $, []);
923 throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`);
928 * Returns an ArrayBuffer generated from the provided W·R·M·G
929 * (Crockford) base32 string.
931 * This function can also be used as a tag for a template literal. The
932 * literal will be interpreted akin to `String.raw`.
934 * ☡ This function throws if the provided string is not a valid W·R·M·G
937 export const wrmgBase32Binary
= ($, ...$s
) =>
938 decodeBase32(sourceFromArgs($, $s
), true);
941 * Returns a (big‐endian) W·R·M·G (Crockford) base32 string created
942 * from the provided typed array, buffer, or (16‐bit) string.
944 * This function can also be used as a tag for a template literal. The
945 * literal will be interpreted akin to `String.raw`.
947 export const wrmgBase32String
= ($, ...$s
) =>
948 encodeBase32(bufferFromArgs($, $s
), true);