|
1 | 1 | import { COMPARATOR, SORT as SORT_IMPL } from "./util/sort";
|
2 |
| -import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH } from "./util/error"; |
| 2 | +import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_NOTIMPLEMENTED } from "./util/error"; |
3 | 3 | import { joinIntegerArray, joinFloatArray } from "./util/string";
|
4 | 4 | import { idof } from "./builtins";
|
5 | 5 | import { ArrayBufferView } from "./arraybuffer";
|
@@ -123,6 +123,10 @@ export class Int8Array extends ArrayBufferView {
|
123 | 123 | return this.join();
|
124 | 124 | }
|
125 | 125 |
|
| 126 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 127 | + SET<Int8Array, i8, U, valueof<U>>(this, source, offset); |
| 128 | + } |
| 129 | + |
126 | 130 | static wrap(buffer: ArrayBuffer, byteOffset: i32 = 0, length: i32 = -1): Int8Array {
|
127 | 131 | return WRAP<Int8Array, i8>(buffer, byteOffset, length);
|
128 | 132 | }
|
@@ -243,6 +247,10 @@ export class Uint8Array extends ArrayBufferView {
|
243 | 247 | return joinIntegerArray<u8>(this.dataStart, this.length, separator);
|
244 | 248 | }
|
245 | 249 |
|
| 250 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 251 | + SET<Uint8Array, u8, U, valueof<U>>(this, source, offset); |
| 252 | + } |
| 253 | + |
246 | 254 | toString(): string {
|
247 | 255 | return this.join();
|
248 | 256 | }
|
@@ -367,6 +375,10 @@ export class Uint8ClampedArray extends ArrayBufferView {
|
367 | 375 | return joinIntegerArray<u8>(this.dataStart, this.length, separator);
|
368 | 376 | }
|
369 | 377 |
|
| 378 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 379 | + SET<Uint8ClampedArray, u8, U, valueof<U>>(this, source, offset); |
| 380 | + } |
| 381 | + |
370 | 382 | toString(): string {
|
371 | 383 | return this.join();
|
372 | 384 | }
|
@@ -491,6 +503,10 @@ export class Int16Array extends ArrayBufferView {
|
491 | 503 | return joinIntegerArray<i16>(this.dataStart, this.length, separator);
|
492 | 504 | }
|
493 | 505 |
|
| 506 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 507 | + SET<Int16Array, i16, U, valueof<U>>(this, source, offset); |
| 508 | + } |
| 509 | + |
494 | 510 | toString(): string {
|
495 | 511 | return this.join();
|
496 | 512 | }
|
@@ -615,6 +631,10 @@ export class Uint16Array extends ArrayBufferView {
|
615 | 631 | return joinIntegerArray<u16>(this.dataStart, this.length, separator);
|
616 | 632 | }
|
617 | 633 |
|
| 634 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 635 | + SET<Uint16Array, u16, U, valueof<U>>(this, source, offset); |
| 636 | + } |
| 637 | + |
618 | 638 | toString(): string {
|
619 | 639 | return this.join();
|
620 | 640 | }
|
@@ -739,6 +759,10 @@ export class Int32Array extends ArrayBufferView {
|
739 | 759 | return joinIntegerArray<i32>(this.dataStart, this.length, separator);
|
740 | 760 | }
|
741 | 761 |
|
| 762 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 763 | + SET<Int32Array, i32, U, valueof<U>>(this, source, offset); |
| 764 | + } |
| 765 | + |
742 | 766 | toString(): string {
|
743 | 767 | return this.join();
|
744 | 768 | }
|
@@ -863,6 +887,10 @@ export class Uint32Array extends ArrayBufferView {
|
863 | 887 | return joinIntegerArray<u32>(this.dataStart, this.length, separator);
|
864 | 888 | }
|
865 | 889 |
|
| 890 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 891 | + SET<Uint32Array, u32, U, valueof<U>>(this, source, offset); |
| 892 | + } |
| 893 | + |
866 | 894 | toString(): string {
|
867 | 895 | return this.join();
|
868 | 896 | }
|
@@ -987,6 +1015,10 @@ export class Int64Array extends ArrayBufferView {
|
987 | 1015 | return joinIntegerArray<i64>(this.dataStart, this.length, separator);
|
988 | 1016 | }
|
989 | 1017 |
|
| 1018 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 1019 | + SET<Int64Array, i64, U, valueof<U>>(this, source, offset); |
| 1020 | + } |
| 1021 | + |
990 | 1022 | toString(): string {
|
991 | 1023 | return this.join();
|
992 | 1024 | }
|
@@ -1111,6 +1143,10 @@ export class Uint64Array extends ArrayBufferView {
|
1111 | 1143 | return joinIntegerArray<u64>(this.dataStart, this.length, separator);
|
1112 | 1144 | }
|
1113 | 1145 |
|
| 1146 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 1147 | + SET<Uint64Array, u64, U, valueof<U>>(this, source, offset); |
| 1148 | + } |
| 1149 | + |
1114 | 1150 | toString(): string {
|
1115 | 1151 | return this.join();
|
1116 | 1152 | }
|
@@ -1235,6 +1271,10 @@ export class Float32Array extends ArrayBufferView {
|
1235 | 1271 | return joinFloatArray<f32>(this.dataStart, this.length, separator);
|
1236 | 1272 | }
|
1237 | 1273 |
|
| 1274 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 1275 | + SET<Float32Array, f32, U, valueof<U>>(this, source, offset); |
| 1276 | + } |
| 1277 | + |
1238 | 1278 | toString(): string {
|
1239 | 1279 | return this.join();
|
1240 | 1280 | }
|
@@ -1359,6 +1399,10 @@ export class Float64Array extends ArrayBufferView {
|
1359 | 1399 | return joinFloatArray<f64>(this.dataStart, this.length, separator);
|
1360 | 1400 | }
|
1361 | 1401 |
|
| 1402 | + set<U extends ArrayBufferView>(source: U, offset: i32 = 0): void { |
| 1403 | + SET<Float64Array, f64, U, valueof<U>>(this, source, offset); |
| 1404 | + } |
| 1405 | + |
1362 | 1406 | toString(): string {
|
1363 | 1407 | return this.join();
|
1364 | 1408 | }
|
@@ -1718,3 +1762,73 @@ function WRAP<TArray extends ArrayBufferView, T>(buffer: ArrayBuffer, byteOffset
|
1718 | 1762 | store<usize>(out, changetype<usize>(buffer) + <usize>byteOffset, offsetof<TArray>("dataStart"));
|
1719 | 1763 | return changetype<TArray>(out); // retains
|
1720 | 1764 | }
|
| 1765 | + |
| 1766 | +// @ts-ignore: decorator |
| 1767 | +@inline |
| 1768 | +function SET<TArray extends ArrayBufferView, T, UArray extends ArrayBufferView, U>(target: TArray, source: UArray, offset: i32 = 0): void { |
| 1769 | + // need to assert at compile time that U is not a reference or a function |
| 1770 | + if (isReference<U>()) { |
| 1771 | + ERROR(E_NOTIMPLEMENTED); |
| 1772 | + } |
| 1773 | + |
| 1774 | + // Uncaught RangeError: offset is out of bounds |
| 1775 | + if (offset < 0) throw new RangeError(E_INDEXOUTOFRANGE); |
| 1776 | + if (source.length + offset > target.length) throw new RangeError(E_INDEXOUTOFRANGE); |
| 1777 | + |
| 1778 | + // if the types align and match, use memory.copy() instead of manual loop |
| 1779 | + if (isInteger<T>() == isInteger<U>() && alignof<T>() == alignof<U>() && |
| 1780 | + !(target instanceof Uint8ClampedArray && isSigned<U>())) { |
| 1781 | + memory.copy( |
| 1782 | + target.dataStart + (<usize>offset << alignof<T>()), |
| 1783 | + source.dataStart, |
| 1784 | + source.byteLength |
| 1785 | + ); |
| 1786 | + } else { |
| 1787 | + let targetDataStart = target.dataStart + (<usize>offset << alignof<T>()); |
| 1788 | + let sourceDataStart = source.dataStart; |
| 1789 | + let count = source.length; |
| 1790 | + for (let i = 0; i < count; i++) { |
| 1791 | + // if TArray is Uint8ClampedArray, then values must be clamped |
| 1792 | + if (target instanceof Uint8ClampedArray) { |
| 1793 | + if (isFloat<U>()) { |
| 1794 | + let value = load<U>(sourceDataStart + (<usize>i << alignof<U>())); |
| 1795 | + store<T>( |
| 1796 | + targetDataStart + (<usize>i << alignof<T>()), |
| 1797 | + isFinite<U>(value) ? <T>max<U>(0, min<U>(255, value)) : 0 |
| 1798 | + ); |
| 1799 | + } else { |
| 1800 | + let value = load<U>(sourceDataStart + (<usize>i << alignof<U>())); |
| 1801 | + if (!isSigned<U>()) { |
| 1802 | + store<T>( |
| 1803 | + targetDataStart + (<usize>i << alignof<T>()), |
| 1804 | + // @ts-ignore: cast to T is valid for numeric types here |
| 1805 | + min<U>(255, value) |
| 1806 | + ); |
| 1807 | + } else if (sizeof<T>() <= 4) { |
| 1808 | + store<T>( |
| 1809 | + targetDataStart + (<usize>i << alignof<T>()), |
| 1810 | + // @ts-ignore: cast to T is valid for numeric types here |
| 1811 | + ~(<i32>value >> 31) & (((255 - <i32>value) >> 31) | value) |
| 1812 | + ); |
| 1813 | + } else { |
| 1814 | + store<T>( |
| 1815 | + targetDataStart + (<usize>i << alignof<T>()), |
| 1816 | + // @ts-ignore: cast to T is valid for numeric types here |
| 1817 | + ~(<i64>value >> 63) & (((255 - <i64>value) >> 63) | value) |
| 1818 | + ); |
| 1819 | + } |
| 1820 | + } |
| 1821 | + // if U is a float, then casting float to int must include a finite check |
| 1822 | + } else if (isFloat<U>() && !isFloat<T>()) { |
| 1823 | + let value = load<U>(sourceDataStart + (<usize>i << alignof<U>())); |
| 1824 | + // @ts-ignore: cast to T is valid for numeric types here |
| 1825 | + store<T>(targetDataStart + (<usize>i << alignof<T>()), isFinite<U>(value) ? <T>value : 0); |
| 1826 | + } else if (isFloat<T>() && !isFloat<U>()) { |
| 1827 | + // @ts-ignore: In this case the <T> conversion is required |
| 1828 | + store<T>(targetDataStart + (<usize>i << alignof<T>()), <T>load<U>(sourceDataStart + (<usize>i << alignof<U>()))); |
| 1829 | + } else { |
| 1830 | + store<T>(targetDataStart + (<usize>i << alignof<T>()), load<U>(sourceDataStart + (<usize>i << alignof<U>()))); |
| 1831 | + } |
| 1832 | + } |
| 1833 | + } |
| 1834 | +} |
0 commit comments