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   getBigInt64: viewGetInt64
, 
  83   getBigUint64: viewGetUint64
, 
  84   getFloat32: viewGetFloat32
, 
  85   getFloat64: viewGetFloat64
, 
  87   getInt16: viewGetInt16
, 
  88   getInt32: viewGetInt32
, 
  89   getUint8: viewGetUint8
, 
  90   getUint16: viewGetUint16
, 
  91   getUint32: viewGetUint32
, 
  92   setFloat32: viewSetFloat32
, 
  93   setFloat64: viewSetFloat64
, 
  94   setUint8: viewSetUint8
, 
  95   setUint16: viewSetUint16
, 
  96   setUint32: viewSetUint32
, 
  97   setBigUint64: viewSetUint64
, 
 101  * Returns an ArrayBuffer for encoding generated from the provided 
 104 const bufferFromArgs 
= ($, $s
) => { 
 106     // Try just getting the array buffer associated with the first 
 107     // argument and returning it if possible. 
 108     return toArrayBuffer($); 
 110     // There is no array buffer associated with the first argument. 
 112     // Construct a string and convert it to an array buffer instead. 
 118           (result
, ucsCharacter
, index
) => ( 
 119             call(viewSetUint16
, result
, [ 
 121               getCodeUnit(ucsCharacter
, 0), 
 124           new View(new Buffer(string
.length 
* 2)), 
 128         typeof $ === "string" 
 130           : hasOwnProperty($, "raw") 
 133             ...objectCreate(argumentIterablePrototype
, { 
 143  * Returns the result of decoding the provided base16 string into an 
 146  * ※ This function is not exposed. 
 148 const decodeBase16 
= (source
) => { 
 152       const code 
= getCodeUnit(ucsCharacter
, 0); 
 153       const result 
= code 
>= 0x30 && code 
<= 0x39 
 155         : code 
>= 0x41 && code 
<= 0x46 
 157         : code 
>= 0x61 && code 
<= 0x66 
 161         // The source contains an invalid character. 
 162         throw new RangeError( 
 163           `Piscēs: Invalid character in Base64: ${ucsCharacter}.`, 
 166         // The source contains a valid character with a recognized 
 172   const { length 
} = u4s
; 
 173   if (length 
% 2 === 1) { 
 174     // The length is such that an entire letter would be dropped during 
 175     // a forgiving decode. 
 176     throw new RangeError( 
 177       `Piscēs: Base16 string has invalid length: ${source}.`, 
 180     // Every letter contributes at least some bits to the result. 
 181     const dataView 
= new View(new Buffer(floor(length 
/ 2))); 
 182     for (let index 
= 0; index 
< length 
- 1;) { 
 183       // Iterate over the characters and assign their bits to the 
 185       call(viewSetUint8
, dataView
, [ 
 187         (u4s
[index
] << 4) | u4s
[++index
, index
++], 
 190     return call(getViewBuffer
, dataView
, []); 
 195  * Returns the result of decoding the provided base32 string into an 
 198  * If the second argument is truthy, uses Crockford’s encoding rather 
 199  * than the RFC’s (see <https://www.crockford.com/base32.html>). This 
 200  * is more human‐friendly and tolerant. Check digits are not supported. 
 202  * ※ This function is not exposed. 
 204 const decodeBase32 
= (source
, wrmg
) => { 
 207       ? stringReplace(source
, /-/gu
, "") 
 208       : source
.length 
% 8 === 0 
 209       ? stringReplace(source
, /(?:=|={3,4}|={6})$/u, "") 
 212       const code 
= getCodeUnit(ucsCharacter
, 0); 
 214         ? code 
>= 0x30 && code 
<= 0x39 
 216           : code 
>= 0x41 && code 
<= 0x48 
 220           : code 
>= 0x4A && code 
<= 0x4B 
 224           : code 
>= 0x4D && code 
<= 0x4E 
 228           : code 
>= 0x50 && code 
<= 0x54 
 231           : code 
>= 0x56 && code 
<= 0x5A 
 233           : code 
>= 0x61 && code 
<= 0x68 
 237           : code 
>= 0x6A && code 
<= 0x6B 
 241           : code 
>= 0x6D && code 
<= 0x6E 
 245           : code 
>= 0x70 && code 
<= 0x74 
 248           : code 
>= 0x76 && code 
<= 0x7A 
 251         : code 
>= 0x41 && code 
<= 0x5A 
 253         : code 
>= 0x61 && code 
<= 0x7A 
 254         ? code 
- 97 // same result as above; case insensitive 
 255         : code 
>= 0x32 && code 
<= 0x37 
 256         ? code 
- 24 // digits 2–7 map to 26–31 
 259         // The source contains an invalid character. 
 260         throw new RangeError( 
 261           `Piscēs: Invalid character in Base32: ${ucsCharacter}.`, 
 264         // The source contains a valid character with a recognized 
 270   const { length 
} = u5s
; 
 271   const lengthMod8 
= length 
% 8; 
 272   if (lengthMod8 
=== 1 || lengthMod8 
=== 3 || lengthMod8 
=== 6) { 
 273     // The length is such that an entire letter would be dropped during 
 274     // a forgiving decode. 
 275     throw new RangeError( 
 276       `Piscēs: Base32 string has invalid length: ${source}.`, 
 279     // Every letter contributes at least some bits to the result. 
 280     const dataView 
= new View(new Buffer(floor(length 
* 5 / 8))); 
 281     for (let index 
= 0; index 
< length 
- 1;) { 
 282       // Iterate over the characters and assign their bits to the 
 285       // The final index is not handled; if the string is not divisible 
 286       // by 8, some bits might be dropped. This matches the “forgiving 
 287       // decode” behaviour specified by WhatW·G for base64. 
 288       const dataIndex 
= ceil(index 
* 5 / 8); 
 289       const remainder 
= index 
% 8; 
 290       call(viewSetUint8
, dataView
, [ 
 293           ? u5s
[index
] << 3 | u5s
[++index
] >> 2 
 295           ? u5s
[index
] << 6 | u5s
[++index
] << 1 | u5s
[++index
] >> 4 
 297           ? u5s
[index
] << 4 | u5s
[++index
] >> 1 
 299           ? u5s
[index
] << 7 | u5s
[++index
] << 2 | u5s
[++index
] >> 3 
 300           : u5s
[index
] << 5 | u5s
[++index
, index
++], // remainder === 6 
 303     return call(getViewBuffer
, dataView
, []); 
 308  * Returns the result of decoding the provided base64 string into an 
 311  * ※ This function is not exposed. 
 313 const decodeBase64 
= (source
, safe 
= false) => { 
 315     source
.length 
% 4 === 0 
 316       ? stringReplace(source
, /={1,2}$/u, "") 
 319       const code 
= getCodeUnit(ucsCharacter
, 0); 
 320       const result 
= code 
>= 0x41 && code 
<= 0x5A 
 322         : code 
>= 0x61 && code 
<= 0x7A 
 324         : code 
>= 0x30 && code 
<= 0x39 
 326         : code 
=== (safe 
? 0x2D : 0x2B) 
 328         : code 
=== (safe 
? 0x5F : 0x2F) 
 332         // The source contains an invalid character. 
 333         throw new RangeError( 
 334           `Piscēs: Invalid character in Base64: ${ucsCharacter}.`, 
 337         // The source contains a valid character with a recognized 
 343   const { length 
} = u6s
; 
 344   if (length 
% 4 === 1) { 
 345     // The length is such that an entire letter would be dropped during 
 346     // a forgiving decode. 
 347     throw new RangeError( 
 348       `Piscēs: Base64 string has invalid length: ${source}.`, 
 351     // Every letter contributes at least some bits to the result. 
 352     const dataView 
= new View(new Buffer(floor(length 
* 3 / 4))); 
 353     for (let index 
= 0; index 
< length 
- 1;) { 
 354       // Iterate over the characters and assign their bits to the 
 357       // The final index is not handled; if the string is not divisible 
 358       // by 4, some bits might be dropped. This matches the “forgiving 
 359       // decode” behaviour specified by WhatW·G for base64. 
 360       const dataIndex 
= ceil(index 
* 3 / 4); 
 361       const remainder 
= index 
% 4; 
 362       call(viewSetUint8
, dataView
, [ 
 365           ? u6s
[index
] << 2 | u6s
[++index
] >> 4 
 367           ? u6s
[index
] << 4 | u6s
[++index
] >> 2 
 368           : u6s
[index
] << 6 | u6s
[++index
, index
++], // remainder === 2 
 371     return call(getViewBuffer
, dataView
, []); 
 376  * Returns the result of encoding the provided ArrayBuffer into a 
 379  * ※ This function is not exposed. 
 381 const encodeBase16 
= (buffer
) => { 
 382   const dataView 
= new View(buffer
); 
 383   const byteLength 
= call(getBufferByteLength
, buffer
, []); 
 384   const minimumLengthOfResults 
= byteLength 
* 2; 
 385   const resultingCodeUnits 
= fill( 
 387       binaryCodeUnitIterablePrototype
, 
 388       { length: { value: minimumLengthOfResults 
} }, 
 392   for (let index 
= 0; index 
< byteLength
;) { 
 393     // Iterate over the bytes and generate code units for them. 
 394     const codeUnitIndex 
= index 
* 2; 
 395     const datum 
= call(viewGetUint8
, dataView
, [index
++]); 
 396     const u4s 
= [datum 
>> 4, datum 
& 0xF]; 
 397     for (let u4i 
= 0; u4i 
< 2; ++u4i
) { 
 398       // Handle the high four bits, then the low four bits. 
 400       const result 
= u4 
< 10 ? u4 
+ 48 : u4 
< 16 ? u4 
+ 55 : -1; 
 402         // No mapping exists for these four bits. 
 404         // ※ This shouldn’t be possible! 
 405         throw new RangeError( 
 406           `Piscēs: Unexpected Base16 value: ${u4}.`, 
 409         // A mapping exists for the bits. 
 410         resultingCodeUnits
[codeUnitIndex 
+ u4i
] = result
; 
 414   return stringFromCodeUnits(...resultingCodeUnits
); 
 418  * Returns the result of encoding the provided ArrayBuffer into a 
 421  * ※ This function is not exposed. 
 423 const encodeBase32 
= (buffer
, wrmg 
= false) => { 
 424   const dataView 
= new View(buffer
); 
 425   const byteLength 
= call(getBufferByteLength
, buffer
, []); 
 426   const minimumLengthOfResults 
= ceil(byteLength 
* 8 / 5); 
 427   const fillByte 
= wrmg 
? 0x2D : 0x3D; 
 428   const resultingCodeUnits 
= fill( 
 430       binaryCodeUnitIterablePrototype
, 
 433           value: minimumLengthOfResults 
+ 
 434             (8 - (minimumLengthOfResults 
% 8)) % 8, 
 440   for (let index 
= 0; index 
< byteLength
;) { 
 441     // Iterate over the bytes and generate code units for them. 
 442     const codeUnitIndex 
= ceil(index 
* 8 / 5); 
 443     const currentIndex 
= codeUnitIndex 
+ +( 
 444       0b01011 & 1 << index 
% 5 && 
 445       resultingCodeUnits
[codeUnitIndex
] != fillByte
 
 446     ); // bytes 0, 1 & 3 handle two letters; this is for the second 
 447     const remainder 
= currentIndex 
% 8; 
 448     const currentByte 
= call(viewGetUint8
, dataView
, [index
]); 
 450       0b01011010 & 1 << remainder 
&& ++index 
< byteLength
 
 451         // digits 1, 3, 4 & 6 span multiple bytes 
 452         ? call(viewGetUint8
, dataView
, [index
]) 
 454     const u5 
= remainder 
=== 0 
 457       ? (currentByte 
& 0b00000111) << 2 | nextByte 
>> 6 
 459       ? (currentByte 
& 0b00111111) >> 1 
 461       ? (currentByte 
& 0b00000001) << 4 | nextByte 
>> 4 
 463       ? (currentByte 
& 0b00001111) << 1 | nextByte 
>> 7 
 465       ? (currentByte 
& 0b01111111) >> 2 
 467       ? (currentByte 
& 0b00000011) << 3 | nextByte 
>> 5 
 468       : (++index
, currentByte 
& 0b00011111); // remainder === 7 
 470       ? u5 
< 10 ? u5 
+ 48 : u5 
< 18 
 491       // No mapping exists for these five bits. 
 493       // ※ This shouldn’t be possible! 
 494       throw new RangeError(`Piscēs: Unexpected Base32 value: ${u5}.`); 
 496       // A mapping exists for the bits. 
 497       resultingCodeUnits
[currentIndex
] = result
; 
 500   const answer 
= stringFromCodeUnits(...resultingCodeUnits
); 
 501   return wrmg 
? answer
.replace(/-+$/u, "") : answer
; 
 505  * Returns the result of encoding the provided ArrayBuffer into a 
 508  * ※ This function is not exposed. 
 510 const encodeBase64 
= (buffer
, safe 
= false) => { 
 511   const dataView 
= new View(buffer
); 
 512   const byteLength 
= call(getBufferByteLength
, buffer
, []); 
 513   const minimumLengthOfResults 
= ceil(byteLength 
* 4 / 3); 
 514   const resultingCodeUnits 
= fill( 
 516       binaryCodeUnitIterablePrototype
, 
 519           value: minimumLengthOfResults 
+ 
 520             (4 - (minimumLengthOfResults 
% 4)) % 4, 
 526   for (let index 
= 0; index 
< byteLength
;) { 
 527     // Iterate over the bytes and generate code units for them. 
 528     const codeUnitIndex 
= ceil(index 
* 4 / 3); 
 529     const currentIndex 
= codeUnitIndex 
+ +( 
 530       index 
% 3 === 0 && resultingCodeUnits
[codeUnitIndex
] != 0x3D 
 531     ); // every third byte handles two letters; this is for the second 
 532     const remainder 
= currentIndex 
% 4; 
 533     const currentByte 
= call(viewGetUint8
, dataView
, [index
]); 
 534     const nextByte 
= remainder 
% 3 && ++index 
< byteLength
 
 535       // digits 1 & 2 span multiple bytes 
 536       ? call(viewGetUint8
, dataView
, [index
]) 
 538     const u6 
= remainder 
=== 0 
 541       ? (currentByte 
& 0b00000011) << 4 | nextByte 
>> 4 
 543       ? (currentByte 
& 0b00001111) << 2 | nextByte 
>> 6 
 544       : (++index
, currentByte 
& 0b00111111); // remainder === 3 
 545     const result 
= u6 
< 26 
 552       ? (safe 
? 0x2D : 0x2B) 
 554       ? (safe 
? 0x5F : 0x2F) 
 557       // No mapping exists for these six bits. 
 559       // ※ This shouldn’t be possible! 
 560       throw new RangeError(`Piscēs: Unexpected Base64 value: ${u6}.`); 
 562       // A mapping exists for the bits. 
 563       resultingCodeUnits
[currentIndex
] = result
; 
 566   return stringFromCodeUnits(...resultingCodeUnits
); 
 570  * Returns a source string generated from the arguments passed to a 
 573  * ※ This function is not exposed. 
 575 const sourceFromArgs 
= ($, $s
) => 
 577     typeof $ === "string" ? $ : hasOwnProperty($, "raw") 
 580         ...objectCreate(argumentIterablePrototype
, { 
 590  * Returns a slice of the provided value according to the algorithm of 
 591  * `ArrayBuffer::slice` (or `SharedArrayBuffer::slice`). 
 593  * ☡ This function throws if the provided value is not an array buffer. 
 595 export const arrayBufferSlice 
= ($, start
, end
, ...args
) => 
 597     isSharedArrayBuffer($) ? sharedBufferSlice : bufferSlice
, 
 603         argumentIterablePrototype
, 
 604         { args: { value: args 
} }, 
 610  * Returns an ArrayBuffer generated from the provided base16 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  * ☡ This function throws if the provided string is not a valid base16 
 618 export const base16Binary 
= ($, ...$s
) => 
 619   decodeBase16(sourceFromArgs($, $s
)); 
 622  * Returns a (big‐endian) base16 string created from the provided typed 
 623  * array, buffer, or (16‐bit) string. 
 625  * This function can also be used as a tag for a template literal. The 
 626  * literal will be interpreted akin to `String.raw`. 
 628 export const base16String 
= ($, ...$s
) => 
 629   encodeBase16(bufferFromArgs($, $s
)); 
 632  * Returns an ArrayBuffer generated from the provided base32 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  * ☡ This function throws if the provided string is not a valid base32 
 640 export const base32Binary 
= ($, ...$s
) => 
 641   decodeBase32(sourceFromArgs($, $s
)); 
 644  * Returns a (big‐endian) base32 string created from the provided typed 
 645  * array, buffer, or (16‐bit) string. 
 647  * This function can also be used as a tag for a template literal. The 
 648  * literal will be interpreted akin to `String.raw`. 
 650 export const base32String 
= ($, ...$s
) => 
 651   encodeBase32(bufferFromArgs($, $s
)); 
 654  * Returns an ArrayBuffer generated from the provided base64 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  * ☡ This function throws if the provided string is not a valid base64 
 662 export const base64Binary 
= ($, ...$s
) => 
 663   decodeBase64(sourceFromArgs($, $s
)); 
 666  * Returns a (big‐endian) base64 string created from the provided typed 
 667  * array, buffer, or (16‐bit) string. 
 669  * This function can also be used as a tag for a template literal. The 
 670  * literal will be interpreted akin to `String.raw`. 
 672 export const base64String 
= ($, ...$s
) => 
 673   encodeBase64(bufferFromArgs($, $s
)); 
 676  * Returns an ArrayBuffer generated from the provided filename‐safe 
 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  * ☡ This function throws if the provided string is not a valid 
 683  * filename‐safe base64 string. 
 685 export const filenameSafeBase64Binary 
= ($, ...$s
) => 
 686   decodeBase64(sourceFromArgs($, $s
), true); 
 689  * Returns a (big‐endian) filename‐safe base64 string created from the 
 690  * provided typed array, buffer, or (16‐bit) string. 
 692  * This function can also be used as a tag for a template literal. The 
 693  * literal will be interpreted akin to `String.raw`. 
 695 export const filenameSafeBase64String 
= ($, ...$s
) => 
 696   encodeBase64(bufferFromArgs($, $s
), true); 
 700    * Returns the signed 8‐bit integral value in the provided array 
 701    * buffer or array buffer view at the provided byte offset. 
 703    * ※ The retrieved value will be big·endian unless a third argument 
 704    * is specified and truthy. 
 706    * ※ This is similar to `DataView::getInt8`, but works on all array 
 707    * buffers and array buffer views and returns a big·int. 
 709    * ☡ This function throws if the first argument is not an array 
 710    * buffer, data view, or typed array. 
 712   get8BitSignedIntegralItem
, 
 715    * Returns the unsigned 8‐bit integral value in the provided array 
 716    * buffer or array buffer view at the provided byte offset. 
 718    * ※ The retrieved value will be big·endian unless a third argument 
 719    * is specified and truthy. 
 721    * ※ This is similar to `DataView::getUint8`, but works on all array 
 722    * buffers and array buffer views and returns a big·int. 
 724    * ☡ This function throws if the first argument is not an array 
 725    * buffer, data view, or typed array. 
 727   get8BitUnsignedIntegralItem
, 
 730    * Returns the signed 16‐bit integral value in the provided array 
 731    * buffer or array buffer view at the provided byte offset. 
 733    * ※ The retrieved value will be big·endian unless a third argument 
 734    * is specified and truthy. 
 736    * ※ This is similar to `DataView::getInt16`, but works on all array 
 737    * buffers and array buffer views and returns a big·int. 
 739    * ☡ This function throws if the first argument is not an array 
 740    * buffer, data view, or typed array. 
 742   get16BitSignedIntegralItem
, 
 745    * Returns the unsigned 16‐bit integral value in the provided array 
 746    * buffer or array buffer view at the provided byte offset. 
 748    * ※ The retrieved value will be big·endian unless a third argument 
 749    * is specified and truthy. 
 751    * ※ This is similar to `DataView::getUint16`, but works on all 
 752    * array buffers and array buffer views and returns a big·int. 
 754    * ☡ This function throws if the first argument is not an array 
 755    * buffer, data view, or typed array. 
 757   get16BitUnsignedIntegralItem
, 
 760    * Returns the 32‐bit floating point value in the provided array 
 761    * buffer or array buffer view at the provided byte offset. 
 763    * ※ The retrieved value will be big·endian unless a third argument 
 764    * is specified and truthy. 
 766    * ※ This is similar to `DataView::getFloat32`, but works on all 
 767    * array buffers and array buffer views. 
 769    * ☡ This function throws if the first argument is not an array 
 770    * buffer, data view, or typed array. 
 772   get32BitFloatingPointItem
, 
 775    * Returns the signed 32‐bit integral value in the provided array 
 776    * buffer or array buffer view at the provided byte offset. 
 778    * ※ The retrieved value will be big·endian unless a third argument 
 779    * is specified and truthy. 
 781    * ※ This is similar to `DataView::getInt32`, but works on all array 
 782    * buffers and array buffer views and returns a big·int. 
 784    * ☡ This function throws if the first argument is not an array 
 785    * buffer, data view, or typed array. 
 787   get32BitSignedIntegralItem
, 
 790    * Returns the unsigned 32‐bit integral value in the provided array 
 791    * buffer or array buffer view at the provided byte offset. 
 793    * ※ The retrieved value will be big·endian unless a third argument 
 794    * is specified and truthy. 
 796    * ※ This is similar to `DataView::getUint32`, but works on all 
 797    * array buffers and array buffer views and returns a big·int. 
 799    * ☡ This function throws if the first argument is not an array 
 800    * buffer, data view, or typed array. 
 802   get32BitUnsignedIntegralItem
, 
 805    * Returns the 64‐bit floating point value in the provided array 
 806    * buffer or array buffer view at the provided byte offset. 
 808    * ※ The retrieved value will be big·endian unless a third argument 
 809    * is specified and truthy. 
 811    * ※ This is similar to `DataView::getFloat64`, but works on all 
 812    * array buffers and array buffer views. 
 814    * ☡ This function throws if the first argument is not an array 
 815    * buffer, data view, or typed array. 
 817   get64BitFloatingPointItem
, 
 820    * Returns the signed 64‐bit integral value in the provided array 
 821    * buffer or array buffer view at the provided byte offset. 
 823    * ※ The retrieved value will be big·endian unless a third argument 
 824    * is specified and truthy. 
 826    * ※ This is similar to `DataView::getBigInt64`, but works on all 
 827    * array buffers and array buffer views. 
 829    * ☡ This function throws if the first argument is not an array 
 830    * buffer, data view, or typed array. 
 832   get64BitSignedIntegralItem
, 
 835    * Returns the unsigned 64‐bit integral value in the provided array 
 836    * buffer or array buffer view at the provided byte offset. 
 838    * ※ The retrieved value will be big·endian unless a third argument 
 839    * is specified and truthy. 
 841    * ※ This is similar to `DataView::getBigUint64`, but works on all 
 842    * array buffers and array buffer views. 
 844    * ☡ This function throws if the first argument is not an array 
 845    * buffer, data view, or typed array. 
 847   get64BitUnsignedIntegralItem
, 
 850    * Sets the 8‐bit integral value in the provided array buffer or 
 851    * array buffer view at the provided byte offset to the provided 
 854    * ※ The value will be set as big·endian unless a fourth argument is 
 855    * specified and truthy. 
 857    * ※ This is similar to `DataView::setInt8`, but works on all array 
 858    * buffers and array buffer views and accepts both numeric and 
 861    * ※ It doesn’t matter whether the provided value is signed or 
 862    * unsigned, as the algorithm will cast one to the other. 
 864    * ☡ This function throws if the first argument is not an array 
 865    * buffer, data view, or typed array. 
 870    * Sets the 16‐bit integral value in the provided array buffer or 
 871    * array buffer view at the provided byte offset to the provided 
 874    * ※ The value will be set as big·endian unless a fourth argument is 
 875    * specified and truthy. 
 877    * ※ This is similar to `DataView::setInt16`, but works on all array 
 878    * buffers and array buffer views and accepts both numeric and 
 881    * ※ It doesn’t matter whether the provided value is signed or 
 882    * unsigned, as the algorithm will cast one to the other. 
 884    * ☡ This function throws if the first argument is not an array 
 885    * buffer, data view, or typed array. 
 887   set16BitIntegralItem
, 
 890    * Sets the 32‐bit floating point value in the provided array buffer 
 891    * or array buffer view at the provided byte offset to the provided 
 894    * ※ The value will be set as big·endian unless a fourth argument is 
 895    * specified and truthy. 
 897    * ※ This is similar to `DataView::setFloat32`, but works on all 
 898    * array buffers and array buffer views. 
 900    * ☡ This function throws if the first argument is not an array 
 901    * buffer, data view, or typed array. 
 903   set32BitFloatingPointItem
, 
 906    * Sets the 32‐bit integral value in the provided array buffer or 
 907    * array buffer view at the provided byte offset to the provided 
 910    * ※ The value will be set as big·endian unless a fourth argument is 
 911    * specified and truthy. 
 913    * ※ This is similar to `DataView::setInt32`, but works on all array 
 914    * buffers and array buffer views and accepts both numeric and 
 917    * ※ It doesn’t matter whether the provided value is signed or 
 918    * unsigned, as the algorithm will cast one to the other. 
 920    * ☡ This function throws if the first argument is not an array 
 921    * buffer, data view, or typed array. 
 923   set32BitIntegralItem
, 
 926    * Sets the 64‐bit floating point value in the provided array buffer 
 927    * or array buffer view at the provided byte offset to the provided 
 930    * ※ The value will be set as big·endian unless a fourth argument is 
 931    * specified and truthy. 
 933    * ※ This is similar to `DataView::setFloat64`, but works on all 
 934    * array buffers and array buffer views. 
 936    * ☡ This function throws if the first argument is not an array 
 937    * buffer, data view, or typed array. 
 939   set64BitFloatingPointItem
, 
 942    * Sets the 64‐bit integral value in the provided array buffer or 
 943    * array buffer view at the provided byte offset to the provided 
 946    * ※ The value will be set as big·endian unless a fourth argument is 
 947    * specified and truthy. 
 949    * ※ This is similar to `DataView::setInt32`, but works on all array 
 950    * buffers and array buffer views. 
 952    * ※ It doesn’t matter whether the provided value is signed or 
 953    * unsigned, as the algorithm will cast one to the other. 
 955    * ☡ This function throws if the first argument is not an array 
 956    * buffer, data view, or typed array, or if the third argument is not 
 959   set64BitIntegralItem
, 
 961   const makeBigInt 
= BigInt
; 
 962   const { asUintN 
} = BigInt
; 
 963   const makeNumber 
= Number
; 
 965   const viewMap 
= new WeakMap(); 
 966   const view 
= ($) => { 
 967     const buffer 
= toArrayBuffer($); 
 968     if (viewMap
.has(buffer
)) { 
 969       // A view has already been allocated for this buffer; use it. 
 970       return viewMap
.get(buffer
); 
 972       // No view has been created for this buffer yet. 
 973       const result 
= new View(buffer
); 
 974       viewMap
.set(buffer
, result
); 
 980     get8BitSignedIntegralItem: ($, byteOffset
, ...args
) => 
 982         call(viewGetInt8
, view($), [ 
 983           getByteOffset($) + byteOffset
, 
 985             argumentIterablePrototype
, 
 986             { args: { value: args 
} }, 
 990     get8BitUnsignedIntegralItem: ($, byteOffset
, ...args
) => 
 992         call(viewGetUint8
, view($), [ 
 993           getByteOffset($) + byteOffset
, 
 995             argumentIterablePrototype
, 
 996             { args: { value: args 
} }, 
1000     get16BitSignedIntegralItem: ($, byteOffset
, ...args
) => 
1002         call(viewGetInt16
, view($), [ 
1003           getByteOffset($) + byteOffset
, 
1005             argumentIterablePrototype
, 
1006             { args: { value: args 
} }, 
1010     get16BitUnsignedIntegralItem: ($, byteOffset
, ...args
) => 
1012         call(viewGetUint16
, view($), [ 
1013           getByteOffset($) + byteOffset
, 
1015             argumentIterablePrototype
, 
1016             { args: { value: args 
} }, 
1020     get32BitFloatingPointItem: ($, byteOffset
, ...args
) => 
1021       call(viewGetFloat32
, view($), [ 
1022         getByteOffset($) + byteOffset
, 
1024           argumentIterablePrototype
, 
1025           { args: { value: args 
} }, 
1028     get32BitSignedIntegralItem: ($, byteOffset
, ...args
) => 
1030         call(viewGetInt32
, view($), [ 
1031           getByteOffset($) + byteOffset
, 
1033             argumentIterablePrototype
, 
1034             { args: { value: args 
} }, 
1038     get32BitUnsignedIntegralItem: ($, byteOffset
, ...args
) => 
1040         call(viewGetUint32
, view($), [ 
1041           getByteOffset($) + byteOffset
, 
1043             argumentIterablePrototype
, 
1044             { args: { value: args 
} }, 
1048     get64BitFloatingPointItem: ($, byteOffset
, ...args
) => 
1049       call(viewGetFloat64
, view($), [ 
1050         getByteOffset($) + byteOffset
, 
1052           argumentIterablePrototype
, 
1053           { args: { value: args 
} }, 
1056     get64BitSignedIntegralItem: ($, byteOffset
, ...args
) => 
1057       call(viewGetInt64
, view($), [ 
1058         getByteOffset($) + byteOffset
, 
1060           argumentIterablePrototype
, 
1061           { args: { value: args 
} }, 
1064     get64BitUnsignedIntegralItem: ($, byteOffset
, ...args
) => 
1065       call(viewGetUint64
, view($), [ 
1066         getByteOffset($) + byteOffset
, 
1068           argumentIterablePrototype
, 
1069           { args: { value: args 
} }, 
1072     set8BitIntegralItem: ($, byteOffset
, value
, ...args
) => 
1073       call(viewSetUint8
, view($), [ 
1074         getByteOffset($) + byteOffset
, 
1077           argumentIterablePrototype
, 
1078           { args: { value: args 
} }, 
1081     set16BitIntegralItem: ($, byteOffset
, value
, ...args
) => 
1082       call(viewSetUint16
, view($), [ 
1083         getByteOffset($) + byteOffset
, 
1086           argumentIterablePrototype
, 
1087           { args: { value: args 
} }, 
1090     set32BitFloatingPointItem: ($, byteOffset
, value
, ...args
) => 
1091       call(viewSetFloat32
, view($), [ 
1092         getByteOffset($) + byteOffset
, 
1095           argumentIterablePrototype
, 
1096           { args: { value: args 
} }, 
1099     set32BitIntegralItem: ($, byteOffset
, value
, ...args
) => 
1100       call(viewSetUint32
, view($), [ 
1101         getByteOffset($) + byteOffset
, 
1104           argumentIterablePrototype
, 
1105           { args: { value: args 
} }, 
1108     set64BitFloatingPointItem: ($, byteOffset
, value
, ...args
) => 
1109       call(viewSetFloat64
, view($), [ 
1110         getByteOffset($) + byteOffset
, 
1113           argumentIterablePrototype
, 
1114           { args: { value: args 
} }, 
1117     set64BitIntegralItem: ($, byteOffset
, value
, ...args
) => 
1118       call(viewSetUint64
, view($), [ 
1119         getByteOffset($) + byteOffset
, 
1122           argumentIterablePrototype
, 
1123           { args: { value: args 
} }, 
1130  * Returns the byte length for the provided array buffer or array 
1133  * ☡ This function throws if the provided value is not an array buffer, 
1134  * data view, or typed array. 
1136 export const getByteLength 
= ($) => { 
1138     // Attempt to get the byte length from the provided value as an 
1140     return call(getBufferByteLength
, $, []); 
1142     // The provided value is not an `ArrayBuffer`. 
1146     // Attempt to get the byte length from the provided value as a 
1147     // `SharedArrayBuffer`. 
1148     return call(getSharedBufferByteLength
, $, []); 
1150     // The provided value is not a `SharedArrayBuffer`. 
1154     // Attempt to get the byte length from the provided value as a 
1156     return call(getViewByteLength
, $, []); 
1158     // The provided value is not a data view. 
1162     // Attempt to get the byte length from the provided value as a 
1164     return call(getTypedArrayByteLength
, $, []); 
1166     // The provided value is not a typed array. 
1169   throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`); 
1173  * Returns the byte offset for the provided array buffer or array 
1176  * ※ This function always returns `0` for array buffers. 
1178  * ☡ This function throws if the provided value is not an array buffer, 
1179  * data view, or typed array. 
1181 export const getByteOffset 
= ($) => { 
1182   if (isArrayBuffer($)) { 
1183     // The provided value is an array buffer. 
1187       // Attempt to get the byte offset from the provided value as a 
1189       return call(getViewByteOffset
, $, []); 
1191       // The provided value is not a data view. 
1195       // Attempt to get the byte offset from the provided value as a 
1197       return call(getTypedArrayByteOffset
, $, []); 
1199       // The provided value is not a typed array. 
1202     throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`); 
1207  * Returns whether the provided value is a view on an underlying array 
1210  * ※ This function returns true for typed arrays and data views. 
1212 export const { isView: isArrayBufferView 
} = Buffer
; 
1215  * Returns whether the provided value is an array buffer. 
1217  * ※ This function returns true for both `ArrayBuffer`s and 
1218  * `SharedArrayBuffer`s. 
1220 export const isArrayBuffer 
= ($) => { 
1222     // Try to see if the provided argument has array buffer internal 
1223     // slots and return true if so. 
1224     return call(getBufferByteLength
, $, []), true; 
1226     // The provided argument does not have array buffer internal slots. 
1230     // Try to see if the provided argument has array buffer internal 
1231     // slots and return true if so. 
1232     return call(getSharedBufferByteLength
, $, []), true; 
1234     // The provided argument does not have array buffer internal slots. 
1241  * Returns whether the provided value is a base16 string. 
1243  * ※ This function returns false if the provided value is not a string 
1246 export const isBase16 
= ($) => { 
1247   if (typeof $ !== "string") { 
1248     // The provided value is not a string. 
1251     // The provided value is a string. 
1252     const source 
= stringReplace($, /[\t\n\f\r ]+/gu
, ""); 
1253     return source
.length 
% 2 !== 1 && 
1254       call(reExec
, /[^0-9A-F]/iu, [source
]) === null; 
1259  * Returns whether the provided value is a base32 string. 
1261  * ※ This function returns false if the provided value is not a string 
1264 export const isBase32 
= ($) => { 
1265   if (typeof $ !== "string") { 
1266     // The provided value is not a string. 
1269     // The provided value is a string. 
1270     const source 
= stringReplace($, /[\t\n\f\r ]+/gu
, ""); 
1271     const trimmed 
= source
.length 
% 8 === 0 
1272       ? stringReplace(source
, /(?:=|={3,4}|={6})$/u, "") 
1274     return trimmed
.length 
% 8 !== 1 && 
1275       call(reExec
, /[^2-7A-Z/]/iu
, [trimmed
]) === null; 
1280  * Returns whether the provided value is a Base64 string. 
1282  * ※ This function returns false if the provided value is not a string 
1285 export const isBase64 
= ($) => { 
1286   if (typeof $ !== "string") { 
1287     // The provided value is not a string. 
1290     // The provided value is a string. 
1291     const source 
= stringReplace($, /[\t\n\f\r ]+/gu
, ""); 
1292     const trimmed 
= source
.length 
% 4 === 0 
1293       ? stringReplace(source
, /={1,2}$/u, "") 
1295     return trimmed
.length 
% 4 !== 1 && 
1296       call(reExec
, /[^0-9A-Za-z+\/]/u, [trimmed
]) === null; 
1301  * Returns whether the provided value is a filename‐safe base64 string. 
1303  * ※ This function returns false if the provided value is not a string 
1306 export const isFilenameSafeBase64 
= ($) => { 
1307   if (typeof $ !== "string") { 
1308     // The provided value is not a string. 
1311     // The provided value is a string. 
1312     const source 
= stringReplace($, /[\t\n\f\r ]+/gu
, ""); 
1313     const trimmed 
= source
.length 
% 4 === 0 
1314       ? stringReplace(source
, /={1,2}$/u, "") 
1316     return trimmed
.length 
% 4 !== 1 && 
1317       call(reExec
, /[^0-9A-Za-z_-]/u, [trimmed
]) === null; 
1321 /** Returns whether the provided value is a shared array buffer. */ 
1322 export const isSharedArrayBuffer 
= ($) => { 
1324     // Try to see if the provided argument has shared array buffer 
1325     // internal slots and return true if so. 
1326     return call(getSharedBufferByteLength
, $, []), true; 
1328     // The provided argument does not have data view internal slots. 
1333 /** Returns whether the provided value is a typed array. */ 
1334 export const isTypedArray 
= ($) => { 
1336     // Try to see if the provided argument has typed array internal 
1337     // slots and return true if so. 
1338     return call(getTypedArrayBuffer
, $, []), true; 
1340     // The provided argument does not have typed array internal slots. 
1346  * Returns whether the provided value is a W·R·M·G (Crockford) base32 
1347  * string. Check digits are not supported. 
1349  * ※ This function returns false if the provided value is not a string 
1352 export const isWRMGBase32 
= ($) => { 
1353   if (typeof $ !== "string") { 
1354     // The provided value is not a string. 
1357     // The provided value is a string. 
1358     const source 
= stringReplace($, /[\t\n\f\r ]+/gu
, ""); 
1359     const trimmed 
= stringReplace(source
, /-/gu
, ""); 
1360     return trimmed
.length 
% 8 !== 1 && 
1361       call(reExec
, /[^0-9A-TV-Z]/iu, [trimmed
]) === null; 
1366  * Returns the array buffer associated with the provided object. 
1368  * ☡ This function throws if the provided object is not a data view or 
1371 export const toArrayBuffer 
= ($) => { 
1372   if (isArrayBuffer($)) { 
1373     // The provided argument has array buffer internal slots. 
1376     // The provided argument does not have array buffer internal slots. 
1378       // The provided argument has typed array internal slots. 
1379       return call(getTypedArrayBuffer
, $, []); 
1384       // The provided argument has data view internal slots. 
1385       return call(getViewBuffer
, $, []); 
1389     throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`); 
1394  * Returns an ArrayBuffer generated from the provided W·R·M·G 
1395  * (Crockford) base32 string. 
1397  * This function can also be used as a tag for a template literal. The 
1398  * literal will be interpreted akin to `String.raw`. 
1400  * ☡ This function throws if the provided string is not a valid W·R·M·G 
1403 export const wrmgBase32Binary 
= ($, ...$s
) => 
1404   decodeBase32(sourceFromArgs($, $s
), true); 
1407  * Returns a (big‐endian) W·R·M·G (Crockford) base32 string created 
1408  * from the provided typed array, buffer, or (16‐bit) string. 
1410  * This function can also be used as a tag for a template literal. The 
1411  * literal will be interpreted akin to `String.raw`. 
1413 export const wrmgBase32String 
= ($, ...$s
) => 
1414   encodeBase32(bufferFromArgs($, $s
), true);