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 { slice
: bufferSlice
} = bufferPrototype
;
61 const getBufferByteLength
=
62 Object
.getOwnPropertyDescriptor(bufferPrototype
, "byteLength").get;
63 const { slice
: sharedBufferSlice
} = sharedBufferPrototype
;
64 const getSharedBufferByteLength
=
65 Object
.getOwnPropertyDescriptor(sharedBufferPrototype
, "byteLength")
67 const getTypedArrayBuffer
=
68 Object
.getOwnPropertyDescriptor(typedArrayPrototype
, "buffer").get;
69 const getTypedArrayByteLength
=
70 Object
.getOwnPropertyDescriptor(typedArrayPrototype
, "byteLength")
72 const getTypedArrayByteOffset
=
73 Object
.getOwnPropertyDescriptor(typedArrayPrototype
, "byteOffset")
76 Object
.getOwnPropertyDescriptor(viewPrototype
, "buffer").get;
77 const getViewByteLength
=
78 Object
.getOwnPropertyDescriptor(viewPrototype
, "byteLength").get;
79 const getViewByteOffset
=
80 Object
.getOwnPropertyDescriptor(viewPrototype
, "byteOffset").get;
82 getUint8
: viewGetUint8
,
83 setUint8
: viewSetUint8
,
84 setUint16
: viewSetUint16
,
88 * Returns an ArrayBuffer for encoding generated from the provided
91 const bufferFromArgs
= ($, $s
) => {
93 // Try just getting the array buffer associated with the first
94 // argument and returning it if possible.
95 return toArrayBuffer($);
97 // There is no array buffer associated with the first argument.
99 // Construct a string and convert it to an array buffer instead.
105 (result
, ucsCharacter
, index
) => (
106 call(viewSetUint16
, result
, [
108 getCodeUnit(ucsCharacter
, 0),
111 new View(new Buffer(string
.length
* 2)),
115 typeof $ === "string"
117 : hasOwnProperty($, "raw")
120 ...objectCreate(argumentIterablePrototype
, {
130 * Returns the result of decoding the provided base16 string into an
133 * ※ This function is not exposed.
135 const decodeBase16
= (source
) => {
139 const code
= getCodeUnit(ucsCharacter
, 0);
140 const result
= code
>= 0x30 && code
<= 0x39
142 : code
>= 0x41 && code
<= 0x46
144 : code
>= 0x61 && code
<= 0x66
148 // The source contains an invalid character.
149 throw new RangeError(
150 `Piscēs: Invalid character in Base64: ${ucsCharacter}.`,
153 // The source contains a valid character with a recognized
159 const { length
} = u4s
;
160 if (length
% 2 === 1) {
161 // The length is such that an entire letter would be dropped during
162 // a forgiving decode.
163 throw new RangeError(
164 `Piscēs: Base16 string has invalid length: ${source}.`,
167 // Every letter contributes at least some bits to the result.
168 const dataView
= new View(new Buffer(floor(length
/ 2)));
169 for (let index
= 0; index
< length
- 1;) {
170 // Iterate over the characters and assign their bits to the
172 call(viewSetUint8
, dataView
, [
174 (u4s
[index
] << 4) | u4s
[++index
, index
++],
177 return call(getViewBuffer
, dataView
, []);
182 * Returns the result of decoding the provided base32 string into an
185 * If the second argument is truthy, uses Crockford’s encoding rather
186 * than the RFC’s (see <https://www.crockford.com/base32.html>). This
187 * is more human‐friendly and tolerant. Check digits are not supported.
189 * ※ This function is not exposed.
191 const decodeBase32
= (source
, wrmg
) => {
194 ? stringReplace(source
, /-/gu
, "")
195 : source
.length
% 8 === 0
196 ? stringReplace(source
, /(?:=|={3,4}|={6})$/u, "")
199 const code
= getCodeUnit(ucsCharacter
, 0);
201 ? code
>= 0x30 && code
<= 0x39
203 : code
>= 0x41 && code
<= 0x48
207 : code
>= 0x4A && code
<= 0x4B
211 : code
>= 0x4D && code
<= 0x4E
215 : code
>= 0x50 && code
<= 0x54
218 : code
>= 0x56 && code
<= 0x5A
220 : code
>= 0x61 && code
<= 0x68
224 : code
>= 0x6A && code
<= 0x6B
228 : code
>= 0x6D && code
<= 0x6E
232 : code
>= 0x70 && code
<= 0x74
235 : code
>= 0x76 && code
<= 0x7A
238 : code
>= 0x41 && code
<= 0x5A
240 : code
>= 0x61 && code
<= 0x7A
241 ? code
- 97 // same result as above; case insensitive
242 : code
>= 0x32 && code
<= 0x37
243 ? code
- 24 // digits 2–7 map to 26–31
246 // The source contains an invalid character.
247 throw new RangeError(
248 `Piscēs: Invalid character in Base32: ${ucsCharacter}.`,
251 // The source contains a valid character with a recognized
257 const { length
} = u5s
;
258 const lengthMod8
= length
% 8;
259 if (lengthMod8
=== 1 || lengthMod8
=== 3 || lengthMod8
=== 6) {
260 // The length is such that an entire letter would be dropped during
261 // a forgiving decode.
262 throw new RangeError(
263 `Piscēs: Base32 string has invalid length: ${source}.`,
266 // Every letter contributes at least some bits to the result.
267 const dataView
= new View(new Buffer(floor(length
* 5 / 8)));
268 for (let index
= 0; index
< length
- 1;) {
269 // Iterate over the characters and assign their bits to the
272 // The final index is not handled; if the string is not divisible
273 // by 8, some bits might be dropped. This matches the “forgiving
274 // decode” behaviour specified by WhatW·G for base64.
275 const dataIndex
= ceil(index
* 5 / 8);
276 const remainder
= index
% 8;
277 call(viewSetUint8
, dataView
, [
280 ? u5s
[index
] << 3 | u5s
[++index
] >> 2
282 ? u5s
[index
] << 6 | u5s
[++index
] << 1 | u5s
[++index
] >> 4
284 ? u5s
[index
] << 4 | u5s
[++index
] >> 1
286 ? u5s
[index
] << 7 | u5s
[++index
] << 2 | u5s
[++index
] >> 3
287 : u5s
[index
] << 5 | u5s
[++index
, index
++], // remainder === 6
290 return call(getViewBuffer
, dataView
, []);
295 * Returns the result of decoding the provided base64 string into an
298 * ※ This function is not exposed.
300 const decodeBase64
= (source
, safe
= false) => {
302 source
.length
% 4 === 0
303 ? stringReplace(source
, /={1,2}$/u, "")
306 const code
= getCodeUnit(ucsCharacter
, 0);
307 const result
= code
>= 0x41 && code
<= 0x5A
309 : code
>= 0x61 && code
<= 0x7A
311 : code
>= 0x30 && code
<= 0x39
313 : code
=== (safe
? 0x2D : 0x2B)
315 : code
=== (safe
? 0x5F : 0x2F)
319 // The source contains an invalid character.
320 throw new RangeError(
321 `Piscēs: Invalid character in Base64: ${ucsCharacter}.`,
324 // The source contains a valid character with a recognized
330 const { length
} = u6s
;
331 if (length
% 4 === 1) {
332 // The length is such that an entire letter would be dropped during
333 // a forgiving decode.
334 throw new RangeError(
335 `Piscēs: Base64 string has invalid length: ${source}.`,
338 // Every letter contributes at least some bits to the result.
339 const dataView
= new View(new Buffer(floor(length
* 3 / 4)));
340 for (let index
= 0; index
< length
- 1;) {
341 // Iterate over the characters and assign their bits to the
344 // The final index is not handled; if the string is not divisible
345 // by 4, some bits might be dropped. This matches the “forgiving
346 // decode” behaviour specified by WhatW·G for base64.
347 const dataIndex
= ceil(index
* 3 / 4);
348 const remainder
= index
% 4;
349 call(viewSetUint8
, dataView
, [
352 ? u6s
[index
] << 2 | u6s
[++index
] >> 4
354 ? u6s
[index
] << 4 | u6s
[++index
] >> 2
355 : u6s
[index
] << 6 | u6s
[++index
, index
++], // remainder === 2
358 return call(getViewBuffer
, dataView
, []);
363 * Returns the result of encoding the provided ArrayBuffer into a
366 * ※ This function is not exposed.
368 const encodeBase16
= (buffer
) => {
369 const dataView
= new View(buffer
);
370 const byteLength
= call(getBufferByteLength
, buffer
, []);
371 const minimumLengthOfResults
= byteLength
* 2;
372 const resultingCodeUnits
= fill(
374 binaryCodeUnitIterablePrototype
,
375 { length
: { value
: minimumLengthOfResults
} },
379 for (let index
= 0; index
< byteLength
;) {
380 // Iterate over the bytes and generate code units for them.
381 const codeUnitIndex
= index
* 2;
382 const datum
= call(viewGetUint8
, dataView
, [index
++]);
383 const u4s
= [datum
>> 4, datum
& 0xF];
384 for (let u4i
= 0; u4i
< 2; ++u4i
) {
385 // Handle the high four bits, then the low four bits.
387 const result
= u4
< 10 ? u4
+ 48 : u4
< 16 ? u4
+ 55 : -1;
389 // No mapping exists for these four bits.
391 // ※ This shouldn’t be possible!
392 throw new RangeError(
393 `Piscēs: Unexpected Base16 value: ${u4}.`,
396 // A mapping exists for the bits.
397 resultingCodeUnits
[codeUnitIndex
+ u4i
] = result
;
401 return stringFromCodeUnits(...resultingCodeUnits
);
405 * Returns the result of encoding the provided ArrayBuffer into a
408 * ※ This function is not exposed.
410 const encodeBase32
= (buffer
, wrmg
= false) => {
411 const dataView
= new View(buffer
);
412 const byteLength
= call(getBufferByteLength
, buffer
, []);
413 const minimumLengthOfResults
= ceil(byteLength
* 8 / 5);
414 const fillByte
= wrmg
? 0x2D : 0x3D;
415 const resultingCodeUnits
= fill(
417 binaryCodeUnitIterablePrototype
,
420 value
: minimumLengthOfResults
+
421 (8 - (minimumLengthOfResults
% 8)) % 8,
427 for (let index
= 0; index
< byteLength
;) {
428 // Iterate over the bytes and generate code units for them.
429 const codeUnitIndex
= ceil(index
* 8 / 5);
430 const currentIndex
= codeUnitIndex
+ +(
431 0b01011 & 1 << index
% 5 &&
432 resultingCodeUnits
[codeUnitIndex
] != fillByte
433 ); // bytes 0, 1 & 3 handle two letters; this is for the second
434 const remainder
= currentIndex
% 8;
435 const currentByte
= call(viewGetUint8
, dataView
, [index
]);
437 0b01011010 & 1 << remainder
&& ++index
< byteLength
438 // digits 1, 3, 4 & 6 span multiple bytes
439 ? call(viewGetUint8
, dataView
, [index
])
441 const u5
= remainder
=== 0
444 ? (currentByte
& 0b00000111) << 2 | nextByte
>> 6
446 ? (currentByte
& 0b00111111) >> 1
448 ? (currentByte
& 0b00000001) << 4 | nextByte
>> 4
450 ? (currentByte
& 0b00001111) << 1 | nextByte
>> 7
452 ? (currentByte
& 0b01111111) >> 2
454 ? (currentByte
& 0b00000011) << 3 | nextByte
>> 5
455 : (++index
, currentByte
& 0b00011111); // remainder === 7
457 ? u5
< 10 ? u5
+ 48 : u5
< 18
478 // No mapping exists for these five bits.
480 // ※ This shouldn’t be possible!
481 throw new RangeError(`Piscēs: Unexpected Base32 value: ${u5}.`);
483 // A mapping exists for the bits.
484 resultingCodeUnits
[currentIndex
] = result
;
487 const answer
= stringFromCodeUnits(...resultingCodeUnits
);
488 return wrmg
? answer
.replace(/-+$/u, "") : answer
;
492 * Returns the result of encoding the provided ArrayBuffer into a
495 * ※ This function is not exposed.
497 const encodeBase64
= (buffer
, safe
= false) => {
498 const dataView
= new View(buffer
);
499 const byteLength
= call(getBufferByteLength
, buffer
, []);
500 const minimumLengthOfResults
= ceil(byteLength
* 4 / 3);
501 const resultingCodeUnits
= fill(
503 binaryCodeUnitIterablePrototype
,
506 value
: minimumLengthOfResults
+
507 (4 - (minimumLengthOfResults
% 4)) % 4,
513 for (let index
= 0; index
< byteLength
;) {
514 // Iterate over the bytes and generate code units for them.
515 const codeUnitIndex
= ceil(index
* 4 / 3);
516 const currentIndex
= codeUnitIndex
+ +(
517 index
% 3 === 0 && resultingCodeUnits
[codeUnitIndex
] != 0x3D
518 ); // every third byte handles two letters; this is for the second
519 const remainder
= currentIndex
% 4;
520 const currentByte
= call(viewGetUint8
, dataView
, [index
]);
521 const nextByte
= remainder
% 3 && ++index
< byteLength
522 // digits 1 & 2 span multiple bytes
523 ? call(viewGetUint8
, dataView
, [index
])
525 const u6
= remainder
=== 0
528 ? (currentByte
& 0b00000011) << 4 | nextByte
>> 4
530 ? (currentByte
& 0b00001111) << 2 | nextByte
>> 6
531 : (++index
, currentByte
& 0b00111111); // remainder === 3
532 const result
= u6
< 26
539 ? (safe
? 0x2D : 0x2B)
541 ? (safe
? 0x5F : 0x2F)
544 // No mapping exists for these six bits.
546 // ※ This shouldn’t be possible!
547 throw new RangeError(`Piscēs: Unexpected Base64 value: ${u6}.`);
549 // A mapping exists for the bits.
550 resultingCodeUnits
[currentIndex
] = result
;
553 return stringFromCodeUnits(...resultingCodeUnits
);
557 * Returns a source string generated from the arguments passed to a
560 * ※ This function is not exposed.
562 const sourceFromArgs
= ($, $s
) =>
564 typeof $ === "string" ? $ : hasOwnProperty($, "raw")
567 ...objectCreate(argumentIterablePrototype
, {
577 * Returns a slice of the provided value according to the algorithm of
578 * `ArrayBuffer::slice` (or `SharedArrayBuffer::slice`).
580 * ☡ This function throws if the provided value is not an array buffer.
582 export const arrayBufferSlice
= ($, start
, end
, ...args
) =>
584 isSharedArrayBuffer($) ? sharedBufferSlice
: bufferSlice
,
590 argumentIterablePrototype
,
591 { args
: { value
: args
} },
597 * Returns an ArrayBuffer generated from the provided base16 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 base16
605 export const base16Binary
= ($, ...$s
) =>
606 decodeBase16(sourceFromArgs($, $s
));
609 * Returns a (big‐endian) base16 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 base16String
= ($, ...$s
) =>
616 encodeBase16(bufferFromArgs($, $s
));
619 * Returns an ArrayBuffer generated from the provided base32 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 base32
627 export const base32Binary
= ($, ...$s
) =>
628 decodeBase32(sourceFromArgs($, $s
));
631 * Returns a (big‐endian) base32 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 base32String
= ($, ...$s
) =>
638 encodeBase32(bufferFromArgs($, $s
));
641 * Returns an ArrayBuffer generated from the provided base64 string.
643 * This function can also be used as a tag for a template literal. The
644 * literal will be interpreted akin to `String.raw`.
646 * ☡ This function throws if the provided string is not a valid base64
649 export const base64Binary
= ($, ...$s
) =>
650 decodeBase64(sourceFromArgs($, $s
));
653 * Returns a (big‐endian) base64 string created from the provided typed
654 * array, buffer, or (16‐bit) string.
656 * This function can also be used as a tag for a template literal. The
657 * literal will be interpreted akin to `String.raw`.
659 export const base64String
= ($, ...$s
) =>
660 encodeBase64(bufferFromArgs($, $s
));
663 * Returns an ArrayBuffer generated from the provided filename‐safe
666 * This function can also be used as a tag for a template literal. The
667 * literal will be interpreted akin to `String.raw`.
669 * ☡ This function throws if the provided string is not a valid
670 * filename‐safe base64 string.
672 export const filenameSafeBase64Binary
= ($, ...$s
) =>
673 decodeBase64(sourceFromArgs($, $s
), true);
676 * Returns a (big‐endian) filename‐safe base64 string created from the
677 * provided typed array, buffer, or (16‐bit) string.
679 * This function can also be used as a tag for a template literal. The
680 * literal will be interpreted akin to `String.raw`.
682 export const filenameSafeBase64String
= ($, ...$s
) =>
683 encodeBase64(bufferFromArgs($, $s
), true);
686 * Returns the byte length for the provided array buffer or array
689 * ☡ This function throws if the provided value is not an array buffer,
690 * data view, or typed array.
692 export const getByteLength
= ($) => {
694 // Attempt to get the byte length from the provided value as an
696 return call(getBufferByteLength
, $, []);
698 // The provided value is not an `ArrayBuffer`.
702 // Attempt to get the byte length from the provided value as a
703 // `SharedArrayBuffer`.
704 return call(getSharedBufferByteLength
, $, []);
706 // The provided value is not a `SharedArrayBuffer`.
710 // Attempt to get the byte length from the provided value as a
712 return call(getViewByteLength
, $, []);
714 // The provided value is not a data view.
718 // Attempt to get the byte length from the provided value as a
720 return call(getTypedArrayByteLength
, $, []);
722 // The provided value is not a typed array.
725 throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`);
729 * Returns the byte offset for the provided array buffer or array
732 * ※ This function always returns `0` for array buffers.
734 * ☡ This function throws if the provided value is not an array buffer,
735 * data view, or typed array.
737 export const getByteOffset
= ($) => {
738 if (isArrayBuffer($)) {
739 // The provided value is an array buffer.
743 // Attempt to get the byte offset from the provided value as a
745 return call(getViewByteOffset
, $, []);
747 // The provided value is not a data view.
751 // Attempt to get the byte offset from the provided value as a
753 return call(getTypedArrayByteOffset
, $, []);
755 // The provided value is not a typed array.
758 throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`);
763 * Returns whether the provided value is a view on an underlying array
766 * ※ This function returns true for typed arrays and data views.
768 export const { isView
: isArrayBufferView
} = Buffer
;
771 * Returns whether the provided value is an array buffer.
773 * ※ This function returns true for both `ArrayBuffer`s and
774 * `SharedArrayBuffer`s.
776 export const isArrayBuffer
= ($) => {
778 // Try to see if the provided argument has array buffer internal
779 // slots and return true if so.
780 return call(getBufferByteLength
, $, []), true;
782 // The provided argument does not have array buffer internal slots.
786 // Try to see if the provided argument has array buffer internal
787 // slots and return true if so.
788 return call(getSharedBufferByteLength
, $, []), true;
790 // The provided argument does not have array buffer internal slots.
797 * Returns whether the provided value is a base16 string.
799 * ※ This function returns false if the provided value is not a string
802 export const isBase16
= ($) => {
803 if (typeof $ !== "string") {
804 // The provided value is not a string.
807 // The provided value is a string.
808 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
809 return source
.length
% 2 !== 1 &&
810 call(reExec
, /[^0-9A-F]/iu, [source
]) === null;
815 * Returns whether the provided value is a base32 string.
817 * ※ This function returns false if the provided value is not a string
820 export const isBase32
= ($) => {
821 if (typeof $ !== "string") {
822 // The provided value is not a string.
825 // The provided value is a string.
826 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
827 const trimmed
= source
.length
% 8 === 0
828 ? stringReplace(source
, /(?:=|={3,4}|={6})$/u, "")
830 return trimmed
.length
% 8 !== 1 &&
831 call(reExec
, /[^2-7A-Z/]/iu
, [trimmed
]) === null;
836 * Returns whether the provided value is a Base64 string.
838 * ※ This function returns false if the provided value is not a string
841 export const isBase64
= ($) => {
842 if (typeof $ !== "string") {
843 // The provided value is not a string.
846 // The provided value is a string.
847 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
848 const trimmed
= source
.length
% 4 === 0
849 ? stringReplace(source
, /={1,2}$/u, "")
851 return trimmed
.length
% 4 !== 1 &&
852 call(reExec
, /[^0-9A-Za-z+\/]/u, [trimmed
]) === null;
857 * Returns whether the provided value is a filename‐safe base64 string.
859 * ※ This function returns false if the provided value is not a string
862 export const isFilenameSafeBase64
= ($) => {
863 if (typeof $ !== "string") {
864 // The provided value is not a string.
867 // The provided value is a string.
868 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
869 const trimmed
= source
.length
% 4 === 0
870 ? stringReplace(source
, /={1,2}$/u, "")
872 return trimmed
.length
% 4 !== 1 &&
873 call(reExec
, /[^0-9A-Za-z_-]/u, [trimmed
]) === null;
877 /** Returns whether the provided value is a shared array buffer. */
878 export const isSharedArrayBuffer
= ($) => {
880 // Try to see if the provided argument has shared array buffer
881 // internal slots and return true if so.
882 return call(getSharedBufferByteLength
, $, []), true;
884 // The provided argument does not have data view internal slots.
889 /** Returns whether the provided value is a typed array. */
890 export const isTypedArray
= ($) => {
892 // Try to see if the provided argument has typed array internal
893 // slots and return true if so.
894 return call(getTypedArrayBuffer
, $, []), true;
896 // The provided argument does not have typed array internal slots.
902 * Returns whether the provided value is a W·R·M·G (Crockford) base32
903 * string. Check digits are not supported.
905 * ※ This function returns false if the provided value is not a string
908 export const isWRMGBase32
= ($) => {
909 if (typeof $ !== "string") {
910 // The provided value is not a string.
913 // The provided value is a string.
914 const source
= stringReplace($, /[\t\n\f\r ]+/gu, "");
915 const trimmed
= stringReplace(source
, /-/gu
, "");
916 return trimmed
.length
% 8 !== 1 &&
917 call(reExec
, /[^0-9A-TV-Z]/iu, [trimmed
]) === null;
922 * Returns the array buffer associated with the provided object.
924 * ☡ This function throws if the provided object is not a data view or
927 export const toArrayBuffer
= ($) => {
928 if (isArrayBuffer($)) {
929 // The provided argument has array buffer internal slots.
932 // The provided argument does not have array buffer internal slots.
934 // The provided argument has typed array internal slots.
935 return call(getTypedArrayBuffer
, $, []);
940 // The provided argument has data view internal slots.
941 return call(getViewBuffer
, $, []);
945 throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`);
950 * Returns an ArrayBuffer generated from the provided W·R·M·G
951 * (Crockford) base32 string.
953 * This function can also be used as a tag for a template literal. The
954 * literal will be interpreted akin to `String.raw`.
956 * ☡ This function throws if the provided string is not a valid W·R·M·G
959 export const wrmgBase32Binary
= ($, ...$s
) =>
960 decodeBase32(sourceFromArgs($, $s
), true);
963 * Returns a (big‐endian) W·R·M·G (Crockford) base32 string created
964 * from the provided typed array, buffer, or (16‐bit) string.
966 * This function can also be used as a tag for a template literal. The
967 * literal will be interpreted akin to `String.raw`.
969 export const wrmgBase32String
= ($, ...$s
) =>
970 encodeBase32(bufferFromArgs($, $s
), true);