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);