๐Ÿ“๐Ÿ–ผ๏ธ๐Ÿน A small thing where I can upload a file and get a link back. https://media.strawmelonjuice.com/
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Delete dashboard/src/prelude.mjs

-1575
-1575
dashboard/src/prelude.mjs
··· 1 - export class CustomType { 2 - withFields(fields) { 3 - let properties = Object.keys(this).map((label) => 4 - label in fields ? fields[label] : this[label], 5 - ); 6 - return new this.constructor(...properties); 7 - } 8 - } 9 - 10 - export class List { 11 - static fromArray(array, tail) { 12 - let t = tail || new Empty(); 13 - for (let i = array.length - 1; i >= 0; --i) { 14 - t = new NonEmpty(array[i], t); 15 - } 16 - return t; 17 - } 18 - 19 - [Symbol.iterator]() { 20 - return new ListIterator(this); 21 - } 22 - 23 - toArray() { 24 - return [...this]; 25 - } 26 - 27 - atLeastLength(desired) { 28 - let current = this; 29 - while (desired-- > 0 && current) current = current.tail; 30 - return current !== undefined; 31 - } 32 - 33 - hasLength(desired) { 34 - let current = this; 35 - while (desired-- > 0 && current) current = current.tail; 36 - return desired === -1 && current instanceof Empty; 37 - } 38 - 39 - countLength() { 40 - let current = this; 41 - let length = 0; 42 - while (current) { 43 - current = current.tail; 44 - length++; 45 - } 46 - return length - 1; 47 - } 48 - } 49 - 50 - export function prepend(element, tail) { 51 - return new NonEmpty(element, tail); 52 - } 53 - 54 - export function toList(elements, tail) { 55 - return List.fromArray(elements, tail); 56 - } 57 - 58 - class ListIterator { 59 - #current; 60 - 61 - constructor(current) { 62 - this.#current = current; 63 - } 64 - 65 - next() { 66 - if (this.#current instanceof Empty) { 67 - return { done: true }; 68 - } else { 69 - let { head, tail } = this.#current; 70 - this.#current = tail; 71 - return { value: head, done: false }; 72 - } 73 - } 74 - } 75 - 76 - export class Empty extends List {} 77 - export const List$Empty = () => new Empty(); 78 - export const List$isEmpty = (value) => value instanceof Empty; 79 - 80 - export class NonEmpty extends List { 81 - constructor(head, tail) { 82 - super(); 83 - this.head = head; 84 - this.tail = tail; 85 - } 86 - } 87 - export const List$NonEmpty = (head, tail) => new NonEmpty(head, tail); 88 - export const List$isNonEmpty = (value) => value instanceof NonEmpty; 89 - 90 - export const List$NonEmpty$first = (value) => value.head; 91 - export const List$NonEmpty$rest = (value) => value.tail; 92 - 93 - /** 94 - * A bit array is a contiguous sequence of bits similar to Erlang's Binary type. 95 - */ 96 - export class BitArray { 97 - /** 98 - * The size in bits of this bit array's data. 99 - * 100 - * @type {number} 101 - */ 102 - bitSize; 103 - 104 - /** 105 - * The size in bytes of this bit array's data. If this bit array doesn't store 106 - * a whole number of bytes then this value is rounded up. 107 - * 108 - * @type {number} 109 - */ 110 - byteSize; 111 - 112 - /** 113 - * The number of unused high bits in the first byte of this bit array's 114 - * buffer prior to the start of its data. The value of any unused high bits is 115 - * undefined. 116 - * 117 - * The bit offset will be in the range 0-7. 118 - * 119 - * @type {number} 120 - */ 121 - bitOffset; 122 - 123 - /** 124 - * The raw bytes that hold this bit array's data. 125 - * 126 - * If `bitOffset` is not zero then there are unused high bits in the first 127 - * byte of this buffer. 128 - * 129 - * If `bitOffset + bitSize` is not a multiple of 8 then there are unused low 130 - * bits in the last byte of this buffer. 131 - * 132 - * @type {Uint8Array} 133 - */ 134 - rawBuffer; 135 - 136 - /** 137 - * Constructs a new bit array from a `Uint8Array`, an optional size in 138 - * bits, and an optional bit offset. 139 - * 140 - * If no bit size is specified it is taken as `buffer.length * 8`, i.e. all 141 - * bytes in the buffer make up the new bit array's data. 142 - * 143 - * If no bit offset is specified it defaults to zero, i.e. there are no unused 144 - * high bits in the first byte of the buffer. 145 - * 146 - * @param {Uint8Array} buffer 147 - * @param {number} [bitSize] 148 - * @param {number} [bitOffset] 149 - */ 150 - constructor(buffer, bitSize, bitOffset) { 151 - if (!(buffer instanceof Uint8Array)) { 152 - throw globalThis.Error( 153 - "BitArray can only be constructed from a Uint8Array", 154 - ); 155 - } 156 - 157 - this.bitSize = bitSize ?? buffer.length * 8; 158 - this.byteSize = Math.trunc((this.bitSize + 7) / 8); 159 - this.bitOffset = bitOffset ?? 0; 160 - 161 - // Validate the bit size 162 - if (this.bitSize < 0) { 163 - throw globalThis.Error(`BitArray bit size is invalid: ${this.bitSize}`); 164 - } 165 - 166 - // Validate the bit offset 167 - if (this.bitOffset < 0 || this.bitOffset > 7) { 168 - throw globalThis.Error( 169 - `BitArray bit offset is invalid: ${this.bitOffset}`, 170 - ); 171 - } 172 - 173 - // Validate the length of the buffer 174 - if (buffer.length !== Math.trunc((this.bitOffset + this.bitSize + 7) / 8)) { 175 - throw globalThis.Error("BitArray buffer length is invalid"); 176 - } 177 - 178 - this.rawBuffer = buffer; 179 - } 180 - 181 - /** 182 - * Returns a specific byte in this bit array. If the byte index is out of 183 - * range then `undefined` is returned. 184 - * 185 - * When returning the final byte of a bit array with a bit size that's not a 186 - * multiple of 8, the content of the unused low bits are undefined. 187 - * 188 - * @param {number} index 189 - * @returns {number | undefined} 190 - */ 191 - byteAt(index) { 192 - if (index < 0 || index >= this.byteSize) { 193 - return undefined; 194 - } 195 - 196 - return bitArrayByteAt(this.rawBuffer, this.bitOffset, index); 197 - } 198 - 199 - equals(other) { 200 - if (this.bitSize !== other.bitSize) { 201 - return false; 202 - } 203 - 204 - const wholeByteCount = Math.trunc(this.bitSize / 8); 205 - 206 - // If both bit offsets are zero do a byte-aligned equality check which is 207 - // faster 208 - if (this.bitOffset === 0 && other.bitOffset === 0) { 209 - // Compare any whole bytes 210 - for (let i = 0; i < wholeByteCount; i++) { 211 - if (this.rawBuffer[i] !== other.rawBuffer[i]) { 212 - return false; 213 - } 214 - } 215 - 216 - // Compare any trailing bits, excluding unused low bits 217 - const trailingBitsCount = this.bitSize % 8; 218 - if (trailingBitsCount) { 219 - const unusedLowBitCount = 8 - trailingBitsCount; 220 - if ( 221 - this.rawBuffer[wholeByteCount] >> unusedLowBitCount !== 222 - other.rawBuffer[wholeByteCount] >> unusedLowBitCount 223 - ) { 224 - return false; 225 - } 226 - } 227 - } else { 228 - // Compare any whole bytes 229 - for (let i = 0; i < wholeByteCount; i++) { 230 - const a = bitArrayByteAt(this.rawBuffer, this.bitOffset, i); 231 - const b = bitArrayByteAt(other.rawBuffer, other.bitOffset, i); 232 - 233 - if (a !== b) { 234 - return false; 235 - } 236 - } 237 - 238 - // Compare any trailing bits 239 - const trailingBitsCount = this.bitSize % 8; 240 - if (trailingBitsCount) { 241 - const a = bitArrayByteAt( 242 - this.rawBuffer, 243 - this.bitOffset, 244 - wholeByteCount, 245 - ); 246 - const b = bitArrayByteAt( 247 - other.rawBuffer, 248 - other.bitOffset, 249 - wholeByteCount, 250 - ); 251 - 252 - const unusedLowBitCount = 8 - trailingBitsCount; 253 - if (a >> unusedLowBitCount !== b >> unusedLowBitCount) { 254 - return false; 255 - } 256 - } 257 - } 258 - 259 - return true; 260 - } 261 - 262 - /** 263 - * Returns this bit array's internal buffer. 264 - * 265 - * @deprecated Use `BitArray.byteAt()` or `BitArray.rawBuffer` instead. 266 - * 267 - * @returns {Uint8Array} 268 - */ 269 - get buffer() { 270 - bitArrayPrintDeprecationWarning( 271 - "buffer", 272 - "Use BitArray.byteAt() or BitArray.rawBuffer instead", 273 - ); 274 - 275 - if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) { 276 - throw new globalThis.Error( 277 - "BitArray.buffer does not support unaligned bit arrays", 278 - ); 279 - } 280 - 281 - return this.rawBuffer; 282 - } 283 - 284 - /** 285 - * Returns the length in bytes of this bit array's internal buffer. 286 - * 287 - * @deprecated Use `BitArray.bitSize` or `BitArray.byteSize` instead. 288 - * 289 - * @returns {number} 290 - */ 291 - get length() { 292 - bitArrayPrintDeprecationWarning( 293 - "length", 294 - "Use BitArray.bitSize or BitArray.byteSize instead", 295 - ); 296 - 297 - if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) { 298 - throw new globalThis.Error( 299 - "BitArray.length does not support unaligned bit arrays", 300 - ); 301 - } 302 - 303 - return this.rawBuffer.length; 304 - } 305 - } 306 - 307 - export const BitArray$BitArray = (buffer, bitSize, bitOffset) => 308 - new BitArray(buffer, bitSize, bitOffset); 309 - 310 - /** 311 - * Returns the nth byte in the given buffer, after applying the specified bit 312 - * offset. If the index is out of bounds then zero is returned. 313 - * 314 - * @param {Uint8Array} buffer 315 - * @param {number} bitOffset 316 - * @param {number} index 317 - * @returns {number} 318 - */ 319 - function bitArrayByteAt(buffer, bitOffset, index) { 320 - if (bitOffset === 0) { 321 - return buffer[index] ?? 0; 322 - } else { 323 - const a = (buffer[index] << bitOffset) & 0xff; 324 - const b = buffer[index + 1] >> (8 - bitOffset); 325 - 326 - return a | b; 327 - } 328 - } 329 - 330 - export class UtfCodepoint { 331 - constructor(value) { 332 - this.value = value; 333 - } 334 - } 335 - 336 - const isBitArrayDeprecationMessagePrinted = {}; 337 - function bitArrayPrintDeprecationWarning(name, message) { 338 - if (isBitArrayDeprecationMessagePrinted[name]) { 339 - return; 340 - } 341 - 342 - console.warn( 343 - `Deprecated BitArray.${name} property used in JavaScript FFI code. ${message}.`, 344 - ); 345 - 346 - isBitArrayDeprecationMessagePrinted[name] = true; 347 - } 348 - 349 - /** 350 - * Slices a bit array to produce a new bit array. If `end` is not supplied then 351 - * all bits from `start` onward are returned. 352 - * 353 - * If the slice is out of bounds then an exception is thrown. 354 - * 355 - * @param {BitArray} bitArray 356 - * @param {number} start 357 - * @param {number} [end] 358 - * @returns {BitArray} 359 - */ 360 - export function bitArraySlice(bitArray, start, end) { 361 - end ??= bitArray.bitSize; 362 - 363 - bitArrayValidateRange(bitArray, start, end); 364 - 365 - // Handle zero-length slices 366 - if (start === end) { 367 - return new BitArray(new Uint8Array()); 368 - } 369 - 370 - // Early return for slices that cover the whole bit array 371 - if (start === 0 && end === bitArray.bitSize) { 372 - return bitArray; 373 - } 374 - 375 - start += bitArray.bitOffset; 376 - end += bitArray.bitOffset; 377 - 378 - const startByteIndex = Math.trunc(start / 8); 379 - const endByteIndex = Math.trunc((end + 7) / 8); 380 - const byteLength = endByteIndex - startByteIndex; 381 - 382 - // Avoid creating a new Uint8Array if the view of the underlying ArrayBuffer 383 - // is the same. This can occur when slicing off just the first or last bit of 384 - // a bit array, i.e. when only the bit offset or bit size need to be updated. 385 - let buffer; 386 - if (startByteIndex === 0 && byteLength === bitArray.rawBuffer.byteLength) { 387 - buffer = bitArray.rawBuffer; 388 - } else { 389 - buffer = new Uint8Array( 390 - bitArray.rawBuffer.buffer, 391 - bitArray.rawBuffer.byteOffset + startByteIndex, 392 - byteLength, 393 - ); 394 - } 395 - 396 - return new BitArray(buffer, end - start, start % 8); 397 - } 398 - 399 - /** 400 - * Interprets a slice of this bit array as a floating point number, either 401 - * 32-bit or 64-bit, with the specified endianness. 402 - * 403 - * The value of `end - start` must be exactly 32 or 64, otherwise an exception 404 - * will be thrown. 405 - * 406 - * @param {BitArray} bitArray 407 - * @param {number} start 408 - * @param {number} end 409 - * @param {boolean} isBigEndian 410 - * @returns {number} 411 - */ 412 - export function bitArraySliceToFloat(bitArray, start, end, isBigEndian) { 413 - bitArrayValidateRange(bitArray, start, end); 414 - 415 - const floatSize = end - start; 416 - 417 - // Check size is valid 418 - if (floatSize !== 16 && floatSize !== 32 && floatSize !== 64) { 419 - const msg = 420 - `Sized floats must be 16-bit, 32-bit or 64-bit, got size of ` + 421 - `${floatSize} bits`; 422 - throw new globalThis.Error(msg); 423 - } 424 - 425 - start += bitArray.bitOffset; 426 - 427 - const isStartByteAligned = start % 8 === 0; 428 - 429 - // If the bit range is byte aligned then the float can be read directly out 430 - // of the existing buffer 431 - if (isStartByteAligned) { 432 - const view = new DataView( 433 - bitArray.rawBuffer.buffer, 434 - bitArray.rawBuffer.byteOffset + start / 8, 435 - ); 436 - 437 - if (floatSize === 64) { 438 - return view.getFloat64(0, !isBigEndian); 439 - } else if (floatSize === 32) { 440 - return view.getFloat32(0, !isBigEndian); 441 - } else if (floatSize === 16) { 442 - return fp16UintToNumber(view.getUint16(0, !isBigEndian)); 443 - } 444 - } 445 - 446 - // Copy the unaligned bytes into an aligned array so a DataView can be used 447 - const alignedBytes = new Uint8Array(floatSize / 8); 448 - const byteOffset = Math.trunc(start / 8); 449 - for (let i = 0; i < alignedBytes.length; i++) { 450 - alignedBytes[i] = bitArrayByteAt( 451 - bitArray.rawBuffer, 452 - start % 8, 453 - byteOffset + i, 454 - ); 455 - } 456 - 457 - // Read the float out of the aligned buffer 458 - const view = new DataView(alignedBytes.buffer); 459 - if (floatSize === 64) { 460 - return view.getFloat64(0, !isBigEndian); 461 - } else if (floatSize === 32) { 462 - return view.getFloat32(0, !isBigEndian); 463 - } else { 464 - return fp16UintToNumber(view.getUint16(0, !isBigEndian)); 465 - } 466 - } 467 - 468 - /** 469 - * Interprets a slice of this bit array as a signed or unsigned integer with the 470 - * specified endianness. 471 - * 472 - * @param {BitArray} bitArray 473 - * @param {number} start 474 - * @param {number} end 475 - * @param {boolean} isBigEndian 476 - * @param {boolean} isSigned 477 - * @returns {number} 478 - */ 479 - export function bitArraySliceToInt( 480 - bitArray, 481 - start, 482 - end, 483 - isBigEndian, 484 - isSigned, 485 - ) { 486 - bitArrayValidateRange(bitArray, start, end); 487 - 488 - if (start === end) { 489 - return 0; 490 - } 491 - 492 - start += bitArray.bitOffset; 493 - end += bitArray.bitOffset; 494 - 495 - const isStartByteAligned = start % 8 === 0; 496 - const isEndByteAligned = end % 8 === 0; 497 - 498 - // If the slice is byte-aligned then there is no need to handle unaligned 499 - // slices, meaning a simpler and faster implementation can be used instead 500 - if (isStartByteAligned && isEndByteAligned) { 501 - return intFromAlignedSlice( 502 - bitArray, 503 - start / 8, 504 - end / 8, 505 - isBigEndian, 506 - isSigned, 507 - ); 508 - } 509 - 510 - const size = end - start; 511 - 512 - const startByteIndex = Math.trunc(start / 8); 513 - const endByteIndex = Math.trunc((end - 1) / 8); 514 - 515 - // Handle the case of the slice being completely contained in a single byte 516 - if (startByteIndex == endByteIndex) { 517 - const mask = 0xff >> start % 8; 518 - const unusedLowBitCount = (8 - (end % 8)) % 8; 519 - 520 - let value = 521 - (bitArray.rawBuffer[startByteIndex] & mask) >> unusedLowBitCount; 522 - 523 - // For signed integers, if the high bit is set reinterpret as two's 524 - // complement 525 - if (isSigned) { 526 - const highBit = 2 ** (size - 1); 527 - if (value >= highBit) { 528 - value -= highBit * 2; 529 - } 530 - } 531 - 532 - return value; 533 - } 534 - 535 - // The integer value to be read is not aligned and crosses at least one byte 536 - // boundary in the input array 537 - 538 - if (size <= 53) { 539 - return intFromUnalignedSliceUsingNumber( 540 - bitArray.rawBuffer, 541 - start, 542 - end, 543 - isBigEndian, 544 - isSigned, 545 - ); 546 - } else { 547 - return intFromUnalignedSliceUsingBigInt( 548 - bitArray.rawBuffer, 549 - start, 550 - end, 551 - isBigEndian, 552 - isSigned, 553 - ); 554 - } 555 - } 556 - 557 - /** 558 - * Joins the given segments into a new bit array, tightly packing them together. 559 - * Each segment must be one of the following types: 560 - * 561 - * - A `number`: A single byte value in the range 0-255. Values outside this 562 - * range will be wrapped. 563 - * - A `Uint8Array`: A sequence of byte values of any length. 564 - * - A `BitArray`: A sequence of bits of any length, which may not be byte 565 - * aligned. 566 - * 567 - * The bit size of the returned bit array will be the sum of the size in bits 568 - * of the input segments. 569 - * 570 - * @param {(number | Uint8Array | BitArray)[]} segments 571 - * @returns {BitArray} 572 - */ 573 - export function toBitArray(segments) { 574 - if (segments.length === 0) { 575 - return new BitArray(new Uint8Array()); 576 - } 577 - 578 - if (segments.length === 1) { 579 - const segment = segments[0]; 580 - 581 - // When there is a single BitArray segment it can be returned as-is 582 - if (segment instanceof BitArray) { 583 - return segment; 584 - } 585 - 586 - // When there is a single Uint8Array segment, pass it directly to the bit 587 - // array constructor to avoid a copy 588 - if (segment instanceof Uint8Array) { 589 - return new BitArray(segment); 590 - } 591 - 592 - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); 593 - } 594 - 595 - // Count the total number of bits and check if all segments are numbers, i.e. 596 - // single bytes 597 - let bitSize = 0; 598 - let areAllSegmentsNumbers = true; 599 - for (const segment of segments) { 600 - if (segment instanceof BitArray) { 601 - bitSize += segment.bitSize; 602 - areAllSegmentsNumbers = false; 603 - } else if (segment instanceof Uint8Array) { 604 - bitSize += segment.byteLength * 8; 605 - areAllSegmentsNumbers = false; 606 - } else { 607 - bitSize += 8; 608 - } 609 - } 610 - 611 - // If all segments are numbers then pass the segments array directly to the 612 - // Uint8Array constructor 613 - if (areAllSegmentsNumbers) { 614 - return new BitArray(new Uint8Array(/** @type {number[]} */ (segments))); 615 - } 616 - 617 - // Pack the segments into a Uint8Array 618 - const buffer = new Uint8Array(Math.trunc((bitSize + 7) / 8)); 619 - 620 - // The current write position in bits into the above array. Byte-aligned 621 - // segments, i.e. when the cursor is a multiple of 8, are able to be processed 622 - // faster due to being able to copy bytes directly. 623 - let cursor = 0; 624 - 625 - for (let segment of segments) { 626 - const isCursorByteAligned = cursor % 8 === 0; 627 - 628 - if (segment instanceof BitArray) { 629 - if (isCursorByteAligned && segment.bitOffset === 0) { 630 - buffer.set(segment.rawBuffer, cursor / 8); 631 - cursor += segment.bitSize; 632 - 633 - // Zero any unused bits in the last byte of the buffer. Their content is 634 - // undefined and shouldn't be included in the output. 635 - const trailingBitsCount = segment.bitSize % 8; 636 - if (trailingBitsCount !== 0) { 637 - const lastByteIndex = Math.trunc(cursor / 8); 638 - buffer[lastByteIndex] >>= 8 - trailingBitsCount; 639 - buffer[lastByteIndex] <<= 8 - trailingBitsCount; 640 - } 641 - } else { 642 - appendUnalignedBits( 643 - segment.rawBuffer, 644 - segment.bitSize, 645 - segment.bitOffset, 646 - ); 647 - } 648 - } else if (segment instanceof Uint8Array) { 649 - if (isCursorByteAligned) { 650 - buffer.set(segment, cursor / 8); 651 - cursor += segment.byteLength * 8; 652 - } else { 653 - appendUnalignedBits(segment, segment.byteLength * 8, 0); 654 - } 655 - } else { 656 - if (isCursorByteAligned) { 657 - buffer[cursor / 8] = segment; 658 - cursor += 8; 659 - } else { 660 - appendUnalignedBits(new Uint8Array([segment]), 8, 0); 661 - } 662 - } 663 - } 664 - 665 - function appendUnalignedBits(unalignedBits, size, offset) { 666 - if (size === 0) { 667 - return; 668 - } 669 - 670 - const byteSize = Math.trunc(size + 7 / 8); 671 - 672 - const highBitsCount = cursor % 8; 673 - const lowBitsCount = 8 - highBitsCount; 674 - 675 - let byteIndex = Math.trunc(cursor / 8); 676 - 677 - for (let i = 0; i < byteSize; i++) { 678 - let byte = bitArrayByteAt(unalignedBits, offset, i); 679 - 680 - // If this is a partial byte then zero out the trailing bits as their 681 - // content is undefined and shouldn't be included in the output 682 - if (size < 8) { 683 - byte >>= 8 - size; 684 - byte <<= 8 - size; 685 - } 686 - 687 - // Copy the high bits of the input byte to the low bits of the current 688 - // output byte 689 - buffer[byteIndex] |= byte >> highBitsCount; 690 - 691 - let appendedBitsCount = size - Math.max(0, size - lowBitsCount); 692 - size -= appendedBitsCount; 693 - cursor += appendedBitsCount; 694 - 695 - if (size === 0) { 696 - break; 697 - } 698 - 699 - // Copy the low bits of the input byte to the high bits of the next output 700 - // byte 701 - buffer[++byteIndex] = byte << lowBitsCount; 702 - appendedBitsCount = size - Math.max(0, size - highBitsCount); 703 - size -= appendedBitsCount; 704 - cursor += appendedBitsCount; 705 - } 706 - } 707 - 708 - return new BitArray(buffer, bitSize); 709 - } 710 - 711 - /** 712 - * Encodes a floating point value into a `Uint8Array`. This is used to create 713 - * float segments that are part of bit array expressions. 714 - * 715 - * @param {number} value 716 - * @param {number} size 717 - * @param {boolean} isBigEndian 718 - * @returns {Uint8Array} 719 - */ 720 - export function sizedFloat(value, size, isBigEndian) { 721 - if (size !== 16 && size !== 32 && size !== 64) { 722 - const msg = `Sized floats must be 16-bit, 32-bit or 64-bit, got size of ${size} bits`; 723 - throw new globalThis.Error(msg); 724 - } 725 - 726 - if (size === 16) { 727 - return numberToFp16Uint(value, isBigEndian); 728 - } 729 - 730 - const buffer = new Uint8Array(size / 8); 731 - 732 - const view = new DataView(buffer.buffer); 733 - 734 - if (size == 64) { 735 - view.setFloat64(0, value, !isBigEndian); 736 - } else { 737 - view.setFloat32(0, value, !isBigEndian); 738 - } 739 - 740 - return buffer; 741 - } 742 - 743 - /** 744 - * Encodes an integer value into a `Uint8Array`, or a `BitArray` if the size in 745 - * bits is not a multiple of 8. This is used to create integer segments used in 746 - * bit array expressions. 747 - * 748 - * @param {number} value 749 - * @param {number} size 750 - * @param {boolean} isBigEndian 751 - * @returns {Uint8Array | BitArray} 752 - */ 753 - export function sizedInt(value, size, isBigEndian) { 754 - if (size <= 0) { 755 - return new Uint8Array(); 756 - } 757 - 758 - // Fast path when size is 8 bits. This relies on the rounding behavior of the 759 - // Uint8Array constructor. 760 - if (size === 8) { 761 - return new Uint8Array([value]); 762 - } 763 - 764 - // Fast path when size is less than 8 bits: shift the value up to the high 765 - // bits 766 - if (size < 8) { 767 - value <<= 8 - size; 768 - return new BitArray(new Uint8Array([value]), size); 769 - } 770 - 771 - // Allocate output buffer 772 - const buffer = new Uint8Array(Math.trunc((size + 7) / 8)); 773 - 774 - // The number of trailing bits in the final byte. Will be zero if the size is 775 - // an exact number of bytes. 776 - const trailingBitsCount = size % 8; 777 - 778 - // The number of unused bits in the final byte of the buffer 779 - const unusedBitsCount = 8 - trailingBitsCount; 780 - 781 - // For output sizes not exceeding 32 bits the number type is used. For larger 782 - // output sizes the BigInt type is needed. 783 - // 784 - // The code in each of these two paths must be kept in sync. 785 - if (size <= 32) { 786 - if (isBigEndian) { 787 - let i = buffer.length - 1; 788 - 789 - // Set the trailing bits at the end of the output buffer 790 - if (trailingBitsCount) { 791 - buffer[i--] = (value << unusedBitsCount) & 0xff; 792 - value >>= trailingBitsCount; 793 - } 794 - 795 - for (; i >= 0; i--) { 796 - buffer[i] = value; 797 - value >>= 8; 798 - } 799 - } else { 800 - let i = 0; 801 - 802 - const wholeByteCount = Math.trunc(size / 8); 803 - for (; i < wholeByteCount; i++) { 804 - buffer[i] = value; 805 - value >>= 8; 806 - } 807 - 808 - // Set the trailing bits at the end of the output buffer 809 - if (trailingBitsCount) { 810 - buffer[i] = value << unusedBitsCount; 811 - } 812 - } 813 - } else { 814 - const bigTrailingBitsCount = BigInt(trailingBitsCount); 815 - const bigUnusedBitsCount = BigInt(unusedBitsCount); 816 - 817 - let bigValue = BigInt(value); 818 - 819 - if (isBigEndian) { 820 - let i = buffer.length - 1; 821 - 822 - // Set the trailing bits at the end of the output buffer 823 - if (trailingBitsCount) { 824 - buffer[i--] = Number(bigValue << bigUnusedBitsCount); 825 - bigValue >>= bigTrailingBitsCount; 826 - } 827 - 828 - for (; i >= 0; i--) { 829 - buffer[i] = Number(bigValue); 830 - bigValue >>= 8n; 831 - } 832 - } else { 833 - let i = 0; 834 - 835 - const wholeByteCount = Math.trunc(size / 8); 836 - for (; i < wholeByteCount; i++) { 837 - buffer[i] = Number(bigValue); 838 - bigValue >>= 8n; 839 - } 840 - 841 - // Set the trailing bits at the end of the output buffer 842 - if (trailingBitsCount) { 843 - buffer[i] = Number(bigValue << bigUnusedBitsCount); 844 - } 845 - } 846 - } 847 - 848 - // Integers that aren't a whole number of bytes are returned as a BitArray so 849 - // their size in bits is tracked 850 - if (trailingBitsCount) { 851 - return new BitArray(buffer, size); 852 - } 853 - 854 - return buffer; 855 - } 856 - 857 - /** 858 - * Reads an aligned slice of any size as an integer. 859 - * 860 - * @param {BitArray} bitArray 861 - * @param {number} start 862 - * @param {number} end 863 - * @param {boolean} isBigEndian 864 - * @param {boolean} isSigned 865 - * @returns {number} 866 - */ 867 - function intFromAlignedSlice(bitArray, start, end, isBigEndian, isSigned) { 868 - const byteSize = end - start; 869 - 870 - if (byteSize <= 6) { 871 - return intFromAlignedSliceUsingNumber( 872 - bitArray.rawBuffer, 873 - start, 874 - end, 875 - isBigEndian, 876 - isSigned, 877 - ); 878 - } else { 879 - return intFromAlignedSliceUsingBigInt( 880 - bitArray.rawBuffer, 881 - start, 882 - end, 883 - isBigEndian, 884 - isSigned, 885 - ); 886 - } 887 - } 888 - 889 - /** 890 - * Reads an aligned slice up to 48 bits in size as an integer. Uses the 891 - * JavaScript `number` type internally. 892 - * 893 - * @param {Uint8Array} buffer 894 - * @param {number} start 895 - * @param {number} end 896 - * @param {boolean} isBigEndian 897 - * @param {boolean} isSigned 898 - * @returns {number} 899 - */ 900 - function intFromAlignedSliceUsingNumber( 901 - buffer, 902 - start, 903 - end, 904 - isBigEndian, 905 - isSigned, 906 - ) { 907 - const byteSize = end - start; 908 - 909 - let value = 0; 910 - 911 - // Read bytes as an unsigned integer 912 - if (isBigEndian) { 913 - for (let i = start; i < end; i++) { 914 - value *= 256; 915 - value += buffer[i]; 916 - } 917 - } else { 918 - for (let i = end - 1; i >= start; i--) { 919 - value *= 256; 920 - value += buffer[i]; 921 - } 922 - } 923 - 924 - // For signed integers, if the high bit is set reinterpret as two's 925 - // complement 926 - if (isSigned) { 927 - const highBit = 2 ** (byteSize * 8 - 1); 928 - if (value >= highBit) { 929 - value -= highBit * 2; 930 - } 931 - } 932 - 933 - return value; 934 - } 935 - 936 - /** 937 - * Reads an aligned slice of any size as an integer. Uses the JavaScript 938 - * `BigInt` type internally. 939 - * 940 - * @param {Uint8Array} buffer 941 - * @param {number} start 942 - * @param {number} end 943 - * @param {boolean} isBigEndian 944 - * @param {boolean} isSigned 945 - * @returns {number} 946 - */ 947 - function intFromAlignedSliceUsingBigInt( 948 - buffer, 949 - start, 950 - end, 951 - isBigEndian, 952 - isSigned, 953 - ) { 954 - const byteSize = end - start; 955 - 956 - let value = 0n; 957 - 958 - // Read bytes as an unsigned integer value 959 - if (isBigEndian) { 960 - for (let i = start; i < end; i++) { 961 - value *= 256n; 962 - value += BigInt(buffer[i]); 963 - } 964 - } else { 965 - for (let i = end - 1; i >= start; i--) { 966 - value *= 256n; 967 - value += BigInt(buffer[i]); 968 - } 969 - } 970 - 971 - // For signed integers, if the high bit is set reinterpret as two's 972 - // complement 973 - if (isSigned) { 974 - const highBit = 1n << BigInt(byteSize * 8 - 1); 975 - if (value >= highBit) { 976 - value -= highBit * 2n; 977 - } 978 - } 979 - 980 - // Convert the result into a JS number. This may cause quantizing/error on 981 - // values outside JavaScript's safe integer range. 982 - return Number(value); 983 - } 984 - 985 - /** 986 - * Reads an unaligned slice up to 53 bits in size as an integer. Uses the 987 - * JavaScript `number` type internally. 988 - * 989 - * This function assumes that the slice crosses at least one byte boundary in 990 - * the input. 991 - * 992 - * @param {Uint8Array} buffer 993 - * @param {number} start 994 - * @param {number} end 995 - * @param {boolean} isBigEndian 996 - * @param {boolean} isSigned 997 - * @returns {number} 998 - */ 999 - function intFromUnalignedSliceUsingNumber( 1000 - buffer, 1001 - start, 1002 - end, 1003 - isBigEndian, 1004 - isSigned, 1005 - ) { 1006 - const isStartByteAligned = start % 8 === 0; 1007 - 1008 - let size = end - start; 1009 - let byteIndex = Math.trunc(start / 8); 1010 - 1011 - let value = 0; 1012 - 1013 - if (isBigEndian) { 1014 - // Read any leading bits 1015 - if (!isStartByteAligned) { 1016 - const leadingBitsCount = 8 - (start % 8); 1017 - value = buffer[byteIndex++] & ((1 << leadingBitsCount) - 1); 1018 - size -= leadingBitsCount; 1019 - } 1020 - 1021 - // Read any whole bytes 1022 - while (size >= 8) { 1023 - value *= 256; 1024 - value += buffer[byteIndex++]; 1025 - size -= 8; 1026 - } 1027 - 1028 - // Read any trailing bits 1029 - if (size > 0) { 1030 - value *= 2 ** size; 1031 - value += buffer[byteIndex] >> (8 - size); 1032 - } 1033 - } else { 1034 - // For little endian, if the start is aligned then whole bytes can be read 1035 - // directly out of the input array, with the trailing bits handled at the 1036 - // end 1037 - if (isStartByteAligned) { 1038 - let size = end - start; 1039 - let scale = 1; 1040 - 1041 - // Read whole bytes 1042 - while (size >= 8) { 1043 - value += buffer[byteIndex++] * scale; 1044 - scale *= 256; 1045 - size -= 8; 1046 - } 1047 - 1048 - // Read trailing bits 1049 - value += (buffer[byteIndex] >> (8 - size)) * scale; 1050 - } else { 1051 - // Read little endian data where the start is not byte-aligned. This is 1052 - // done by reading whole bytes that cross a byte boundary in the input 1053 - // data, then reading any trailing bits. 1054 - 1055 - const highBitsCount = start % 8; 1056 - const lowBitsCount = 8 - highBitsCount; 1057 - 1058 - let size = end - start; 1059 - let scale = 1; 1060 - 1061 - // Extract whole bytes 1062 - while (size >= 8) { 1063 - const byte = 1064 - (buffer[byteIndex] << highBitsCount) | 1065 - (buffer[byteIndex + 1] >> lowBitsCount); 1066 - 1067 - value += (byte & 0xff) * scale; 1068 - 1069 - scale *= 256; 1070 - size -= 8; 1071 - byteIndex++; 1072 - } 1073 - 1074 - // Read any trailing bits. These trailing bits may cross a byte boundary 1075 - // in the input buffer. 1076 - if (size > 0) { 1077 - const lowBitsUsed = size - Math.max(0, size - lowBitsCount); 1078 - 1079 - let trailingByte = 1080 - (buffer[byteIndex] & ((1 << lowBitsCount) - 1)) >> 1081 - (lowBitsCount - lowBitsUsed); 1082 - 1083 - size -= lowBitsUsed; 1084 - 1085 - if (size > 0) { 1086 - trailingByte *= 2 ** size; 1087 - trailingByte += buffer[byteIndex + 1] >> (8 - size); 1088 - } 1089 - 1090 - value += trailingByte * scale; 1091 - } 1092 - } 1093 - } 1094 - 1095 - // For signed integers, if the high bit is set reinterpret as two's 1096 - // complement 1097 - if (isSigned) { 1098 - const highBit = 2 ** (end - start - 1); 1099 - if (value >= highBit) { 1100 - value -= highBit * 2; 1101 - } 1102 - } 1103 - 1104 - return value; 1105 - } 1106 - 1107 - /** 1108 - * Reads an unaligned slice of any size as an integer. Uses the JavaScript 1109 - * `BigInt` type internally. 1110 - * 1111 - * This function assumes that the slice crosses at least one byte boundary in 1112 - * the input. 1113 - * 1114 - * @param {Uint8Array} buffer 1115 - * @param {number} start 1116 - * @param {number} end 1117 - * @param {boolean} isBigEndian 1118 - * @param {boolean} isSigned 1119 - * @returns {number} 1120 - */ 1121 - function intFromUnalignedSliceUsingBigInt( 1122 - buffer, 1123 - start, 1124 - end, 1125 - isBigEndian, 1126 - isSigned, 1127 - ) { 1128 - const isStartByteAligned = start % 8 === 0; 1129 - 1130 - let size = end - start; 1131 - let byteIndex = Math.trunc(start / 8); 1132 - 1133 - let value = 0n; 1134 - 1135 - if (isBigEndian) { 1136 - // Read any leading bits 1137 - if (!isStartByteAligned) { 1138 - const leadingBitsCount = 8 - (start % 8); 1139 - value = BigInt(buffer[byteIndex++] & ((1 << leadingBitsCount) - 1)); 1140 - size -= leadingBitsCount; 1141 - } 1142 - 1143 - // Read any whole bytes 1144 - while (size >= 8) { 1145 - value *= 256n; 1146 - value += BigInt(buffer[byteIndex++]); 1147 - size -= 8; 1148 - } 1149 - 1150 - // Read any trailing bits 1151 - if (size > 0) { 1152 - value <<= BigInt(size); 1153 - value += BigInt(buffer[byteIndex] >> (8 - size)); 1154 - } 1155 - } else { 1156 - // For little endian, if the start is aligned then whole bytes can be read 1157 - // directly out of the input array, with the trailing bits handled at the 1158 - // end 1159 - if (isStartByteAligned) { 1160 - let size = end - start; 1161 - let shift = 0n; 1162 - 1163 - // Read whole bytes 1164 - while (size >= 8) { 1165 - value += BigInt(buffer[byteIndex++]) << shift; 1166 - shift += 8n; 1167 - size -= 8; 1168 - } 1169 - 1170 - // Read trailing bits 1171 - value += BigInt(buffer[byteIndex] >> (8 - size)) << shift; 1172 - } else { 1173 - // Read little endian data where the start is not byte-aligned. This is 1174 - // done by reading whole bytes that cross a byte boundary in the input 1175 - // data, then reading any trailing bits. 1176 - 1177 - const highBitsCount = start % 8; 1178 - const lowBitsCount = 8 - highBitsCount; 1179 - 1180 - let size = end - start; 1181 - let shift = 0n; 1182 - 1183 - // Extract whole bytes 1184 - while (size >= 8) { 1185 - const byte = 1186 - (buffer[byteIndex] << highBitsCount) | 1187 - (buffer[byteIndex + 1] >> lowBitsCount); 1188 - 1189 - value += BigInt(byte & 0xff) << shift; 1190 - 1191 - shift += 8n; 1192 - size -= 8; 1193 - byteIndex++; 1194 - } 1195 - 1196 - // Read any trailing bits. These trailing bits may cross a byte boundary 1197 - // in the input buffer. 1198 - if (size > 0) { 1199 - const lowBitsUsed = size - Math.max(0, size - lowBitsCount); 1200 - 1201 - let trailingByte = 1202 - (buffer[byteIndex] & ((1 << lowBitsCount) - 1)) >> 1203 - (lowBitsCount - lowBitsUsed); 1204 - 1205 - size -= lowBitsUsed; 1206 - 1207 - if (size > 0) { 1208 - trailingByte <<= size; 1209 - trailingByte += buffer[byteIndex + 1] >> (8 - size); 1210 - } 1211 - 1212 - value += BigInt(trailingByte) << shift; 1213 - } 1214 - } 1215 - } 1216 - 1217 - // For signed integers, if the high bit is set reinterpret as two's 1218 - // complement 1219 - if (isSigned) { 1220 - const highBit = 2n ** BigInt(end - start - 1); 1221 - if (value >= highBit) { 1222 - value -= highBit * 2n; 1223 - } 1224 - } 1225 - 1226 - // Convert the result into a JS number. This may cause quantizing/error on 1227 - // values outside JavaScript's safe integer range. 1228 - return Number(value); 1229 - } 1230 - 1231 - /** 1232 - * Interprets a 16-bit unsigned integer value as a 16-bit floating point value. 1233 - * 1234 - * @param {number} intValue 1235 - * @returns {number} 1236 - */ 1237 - function fp16UintToNumber(intValue) { 1238 - const sign = intValue >= 0x8000 ? -1 : 1; 1239 - const exponent = (intValue & 0x7c00) >> 10; 1240 - const fraction = intValue & 0x03ff; 1241 - 1242 - let value; 1243 - if (exponent === 0) { 1244 - value = 6.103515625e-5 * (fraction / 0x400); 1245 - } else if (exponent === 0x1f) { 1246 - value = fraction === 0 ? Infinity : NaN; 1247 - } else { 1248 - value = Math.pow(2, exponent - 15) * (1 + fraction / 0x400); 1249 - } 1250 - 1251 - return sign * value; 1252 - } 1253 - 1254 - /** 1255 - * Converts a floating point number to bytes for a 16-bit floating point value. 1256 - * 1257 - * @param {number} intValue 1258 - * @param {boolean} isBigEndian 1259 - * @returns {Uint8Array} 1260 - */ 1261 - function numberToFp16Uint(value, isBigEndian) { 1262 - const buffer = new Uint8Array(2); 1263 - 1264 - if (isNaN(value)) { 1265 - buffer[1] = 0x7e; 1266 - } else if (value === Infinity) { 1267 - buffer[1] = 0x7c; 1268 - } else if (value === -Infinity) { 1269 - buffer[1] = 0xfc; 1270 - } else if (value === 0) { 1271 - // Both values are already zero 1272 - } else { 1273 - const sign = value < 0 ? 1 : 0; 1274 - value = Math.abs(value); 1275 - 1276 - let exponent = Math.floor(Math.log2(value)); 1277 - let fraction = value / Math.pow(2, exponent) - 1; 1278 - 1279 - exponent += 15; 1280 - 1281 - if (exponent <= 0) { 1282 - exponent = 0; 1283 - fraction = value / Math.pow(2, -14); 1284 - } else if (exponent >= 31) { 1285 - exponent = 31; 1286 - fraction = 0; 1287 - } 1288 - 1289 - fraction = Math.round(fraction * 1024); 1290 - 1291 - buffer[1] = 1292 - (sign << 7) | ((exponent & 0x1f) << 2) | ((fraction >> 8) & 0x03); 1293 - buffer[0] = fraction & 0xff; 1294 - } 1295 - 1296 - if (isBigEndian) { 1297 - const a = buffer[0]; 1298 - buffer[0] = buffer[1]; 1299 - buffer[1] = a; 1300 - } 1301 - 1302 - return buffer; 1303 - } 1304 - 1305 - /** 1306 - * Throws an exception if the given start and end values are out of bounds for 1307 - * a bit array. 1308 - * 1309 - * @param {BitArray} bitArray 1310 - * @param {number} start 1311 - * @param {number} end 1312 - */ 1313 - function bitArrayValidateRange(bitArray, start, end) { 1314 - if ( 1315 - start < 0 || 1316 - start > bitArray.bitSize || 1317 - end < start || 1318 - end > bitArray.bitSize 1319 - ) { 1320 - const msg = 1321 - `Invalid bit array slice: start = ${start}, end = ${end}, ` + 1322 - `bit size = ${bitArray.bitSize}`; 1323 - throw new globalThis.Error(msg); 1324 - } 1325 - } 1326 - 1327 - /** @type {TextEncoder | undefined} */ 1328 - let utf8Encoder; 1329 - 1330 - /** 1331 - * Returns the UTF-8 bytes for a string. 1332 - * 1333 - * @param {string} string 1334 - * @returns {Uint8Array} 1335 - */ 1336 - export function stringBits(string) { 1337 - utf8Encoder ??= new TextEncoder(); 1338 - return utf8Encoder.encode(string); 1339 - } 1340 - 1341 - /** 1342 - * Returns the UTF-8 bytes for a single UTF codepoint. 1343 - * 1344 - * @param {UtfCodepoint} codepoint 1345 - * @returns {Uint8Array} 1346 - */ 1347 - export function codepointBits(codepoint) { 1348 - return stringBits(String.fromCodePoint(codepoint.value)); 1349 - } 1350 - 1351 - /** 1352 - * Returns the UTF-16 bytes for a string. 1353 - * 1354 - * @param {string} string 1355 - * @param {boolean} isBigEndian 1356 - * @returns {Uint8Array} 1357 - */ 1358 - export function stringToUtf16(string, isBigEndian) { 1359 - const buffer = new ArrayBuffer(string.length * 2); 1360 - const bufferView = new DataView(buffer); 1361 - 1362 - for (let i = 0; i < string.length; i++) { 1363 - bufferView.setUint16(i * 2, string.charCodeAt(i), !isBigEndian); 1364 - } 1365 - 1366 - return new Uint8Array(buffer); 1367 - } 1368 - 1369 - /** 1370 - * Returns the UTF-16 bytes for a single UTF codepoint. 1371 - * 1372 - * @param {UtfCodepoint} codepoint 1373 - * @param {boolean} isBigEndian 1374 - * @returns {Uint8Array} 1375 - */ 1376 - export function codepointToUtf16(codepoint, isBigEndian) { 1377 - return stringToUtf16(String.fromCodePoint(codepoint.value), isBigEndian); 1378 - } 1379 - 1380 - /** 1381 - * Returns the UTF-32 bytes for a string. 1382 - * 1383 - * @param {string} string 1384 - * @param {boolean} isBigEndian 1385 - * @returns {Uint8Array} 1386 - */ 1387 - export function stringToUtf32(string, isBigEndian) { 1388 - const buffer = new ArrayBuffer(string.length * 4); 1389 - const bufferView = new DataView(buffer); 1390 - let length = 0; 1391 - 1392 - for (let i = 0; i < string.length; i++) { 1393 - const codepoint = string.codePointAt(i); 1394 - 1395 - bufferView.setUint32(length * 4, codepoint, !isBigEndian); 1396 - length++; 1397 - 1398 - if (codepoint > 0xffff) { 1399 - i++; 1400 - } 1401 - } 1402 - 1403 - return new Uint8Array(buffer.slice(0, length * 4)); 1404 - } 1405 - 1406 - /** 1407 - * Returns the UTF-32 bytes for a single UTF codepoint. 1408 - * 1409 - * @param {UtfCodepoint} codepoint 1410 - * @param {boolean} isBigEndian 1411 - * @returns {Uint8Array} 1412 - */ 1413 - export function codepointToUtf32(codepoint, isBigEndian) { 1414 - return stringToUtf32(String.fromCodePoint(codepoint.value), isBigEndian); 1415 - } 1416 - 1417 - export class Result extends CustomType { 1418 - static isResult(data) { 1419 - return data instanceof Result; 1420 - } 1421 - } 1422 - 1423 - export class Ok extends Result { 1424 - constructor(value) { 1425 - super(); 1426 - this[0] = value; 1427 - } 1428 - 1429 - isOk() { 1430 - return true; 1431 - } 1432 - } 1433 - export const Result$Ok = (value) => new Ok(value); 1434 - export const Result$isOk = (value) => value instanceof Ok; 1435 - export const Result$Ok$0 = (value) => value[0]; 1436 - 1437 - export class Error extends Result { 1438 - constructor(detail) { 1439 - super(); 1440 - this[0] = detail; 1441 - } 1442 - 1443 - isOk() { 1444 - return false; 1445 - } 1446 - } 1447 - export const Result$Error = (detail) => new Error(detail); 1448 - export const Result$isError = (value) => value instanceof Error; 1449 - export const Result$Error$0 = (value) => value[0]; 1450 - 1451 - export function isEqual(x, y) { 1452 - let values = [x, y]; 1453 - 1454 - while (values.length) { 1455 - let a = values.pop(); 1456 - let b = values.pop(); 1457 - if (a === b) continue; 1458 - 1459 - if (!isObject(a) || !isObject(b)) return false; 1460 - let unequal = 1461 - !structurallyCompatibleObjects(a, b) || 1462 - unequalDates(a, b) || 1463 - unequalBuffers(a, b) || 1464 - unequalArrays(a, b) || 1465 - unequalMaps(a, b) || 1466 - unequalSets(a, b) || 1467 - unequalRegExps(a, b); 1468 - if (unequal) return false; 1469 - 1470 - const proto = Object.getPrototypeOf(a); 1471 - if (proto !== null && typeof proto.equals === "function") { 1472 - try { 1473 - if (a.equals(b)) continue; 1474 - else return false; 1475 - } catch {} 1476 - } 1477 - 1478 - let [keys, get] = getters(a); 1479 - const ka = keys(a); 1480 - const kb = keys(b); 1481 - if (ka.length !== kb.length) return false; 1482 - for (let k of ka) { 1483 - values.push(get(a, k), get(b, k)); 1484 - } 1485 - } 1486 - 1487 - return true; 1488 - } 1489 - 1490 - function getters(object) { 1491 - if (object instanceof Map) { 1492 - return [(x) => x.keys(), (x, y) => x.get(y)]; 1493 - } else { 1494 - let extra = object instanceof globalThis.Error ? ["message"] : []; 1495 - return [(x) => [...extra, ...Object.keys(x)], (x, y) => x[y]]; 1496 - } 1497 - } 1498 - 1499 - function unequalDates(a, b) { 1500 - return a instanceof Date && (a > b || a < b); 1501 - } 1502 - 1503 - function unequalBuffers(a, b) { 1504 - return ( 1505 - !(a instanceof BitArray) && 1506 - a.buffer instanceof ArrayBuffer && 1507 - a.BYTES_PER_ELEMENT && 1508 - !(a.byteLength === b.byteLength && a.every((n, i) => n === b[i])) 1509 - ); 1510 - } 1511 - 1512 - function unequalArrays(a, b) { 1513 - return Array.isArray(a) && a.length !== b.length; 1514 - } 1515 - 1516 - function unequalMaps(a, b) { 1517 - return a instanceof Map && a.size !== b.size; 1518 - } 1519 - 1520 - function unequalSets(a, b) { 1521 - return ( 1522 - a instanceof Set && (a.size != b.size || [...a].some((e) => !b.has(e))) 1523 - ); 1524 - } 1525 - 1526 - function unequalRegExps(a, b) { 1527 - return a instanceof RegExp && (a.source !== b.source || a.flags !== b.flags); 1528 - } 1529 - 1530 - function isObject(a) { 1531 - return typeof a === "object" && a !== null; 1532 - } 1533 - 1534 - function structurallyCompatibleObjects(a, b) { 1535 - if (typeof a !== "object" && typeof b !== "object" && (!a || !b)) 1536 - return false; 1537 - 1538 - let nonstructural = [Promise, WeakSet, WeakMap, Function]; 1539 - if (nonstructural.some((c) => a instanceof c)) return false; 1540 - 1541 - return a.constructor === b.constructor; 1542 - } 1543 - 1544 - export function remainderInt(a, b) { 1545 - if (b === 0) { 1546 - return 0; 1547 - } else { 1548 - return a % b; 1549 - } 1550 - } 1551 - 1552 - export function divideInt(a, b) { 1553 - return Math.trunc(divideFloat(a, b)); 1554 - } 1555 - 1556 - export function divideFloat(a, b) { 1557 - if (b === 0) { 1558 - return 0; 1559 - } else { 1560 - return a / b; 1561 - } 1562 - } 1563 - 1564 - export function makeError(variant, file, module, line, fn, message, extra) { 1565 - let error = new globalThis.Error(message); 1566 - error.gleam_error = variant; 1567 - error.file = file; 1568 - error.module = module; 1569 - error.line = line; 1570 - error.function = fn; 1571 - // TODO: Remove this with Gleam v2.0.0 1572 - error.fn = fn; 1573 - for (let k in extra) error[k] = extra[k]; 1574 - return error; 1575 - }