Skip to content

Commit 880b2d5

Browse files
authored
feat: Add more methods for StaticArray (#2068)
1 parent 2d45564 commit 880b2d5

File tree

6 files changed

+5919
-2810
lines changed

6 files changed

+5919
-2810
lines changed

std/assembly/array.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ export class Array<T> {
431431
return result;
432432
}
433433

434-
reverse(): Array<T> {
434+
reverse(): this {
435435
REVERSE<T>(this.dataStart, this.length_);
436436
return this;
437437
}

std/assembly/index.d.ts

+17-5
Original file line numberDiff line numberDiff line change
@@ -1691,9 +1691,8 @@ declare class Array<T> {
16911691
constructor(length?: i32);
16921692
at(index: i32): T;
16931693
fill(value: T, start?: i32, end?: i32): this;
1694-
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
1695-
findIndex(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): i32;
1696-
findLastIndex(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): i32;
1694+
findIndex(callbackfn: (value: T, index: i32, array: Array<T>) => bool): i32;
1695+
findLastIndex(callbackfn: (value: T, index: i32, array: Array<T>) => bool): i32;
16971696
includes(searchElement: T, fromIndex?: i32): bool;
16981697
indexOf(searchElement: T, fromIndex?: i32): i32;
16991698
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
@@ -1706,14 +1705,15 @@ declare class Array<T> {
17061705
filter(callbackfn: (value: T, index: i32, array: Array<T>) => bool): Array<T>;
17071706
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U, initialValue: U): U;
17081707
reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U, initialValue: U): U;
1708+
every(callbackfn: (value: T, index: i32, array: Array<T>) => bool): bool;
1709+
some(callbackfn: (value: T, index: i32, array: Array<T>) => bool): bool;
17091710
shift(): T;
1710-
some(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
17111711
unshift(element: T): i32;
17121712
slice(from: i32, to?: i32): Array<T>;
17131713
splice(start: i32, deleteCount?: i32): Array<T>;
17141714
sort(comparator?: (a: T, b: T) => i32): this;
17151715
join(separator?: string): string;
1716-
reverse(): T[];
1716+
reverse(): this;
17171717
/** Flattens an array of arrays. If any null entries exist in the array, they are ignored, unlike JavaScript's version of Array#flat(). */
17181718
flat(): T extends unknown[] ? T : never;
17191719
toString(): string;
@@ -1728,13 +1728,25 @@ declare class StaticArray<T> {
17281728
readonly length: i32;
17291729
constructor(length?: i32);
17301730
at(index: i32): T;
1731+
fill(value: T, start?: i32, end?: i32): this;
1732+
findIndex(callbackfn: (value: T, index: i32, array: StaticArray<T>) => bool): i32;
1733+
findLastIndex(callbackfn: (value: T, index: i32, array: StaticArray<T>) => bool): i32;
1734+
copyWithin(target: i32, start: i32, end?: i32): this;
17311735
includes(searchElement: T, fromIndex?: i32): bool;
17321736
indexOf(searchElement: T, fromIndex?: i32): i32;
17331737
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
1738+
forEach(callbackfn: (value: T, index: i32, array: StaticArray<T>) => void): void;
1739+
map<U>(callbackfn: (value: T, index: i32, array: StaticArray<T>) => U): Array<U>;
1740+
filter(callbackfn: (value: T, index: i32, array: StaticArray<T>) => bool): Array<T>;
1741+
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: i32, array: StaticArray<T>) => U, initialValue: U): U;
1742+
reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: i32, array: StaticArray<T>) => U, initialValue: U): U;
1743+
every(callbackfn: (value: T, index: i32, array: StaticArray<T>) => bool): bool;
1744+
some(callbackfn: (value: T, index: i32, array: StaticArray<T>) => bool): bool;
17341745
concat(items: Array<T>): Array<T>;
17351746
slice(from: i32, to?: i32): Array<T>;
17361747
sort(comparator?: (a: T, b: T) => i32): this;
17371748
join(separator?: string): string;
1749+
reverse(): this;
17381750
toString(): string;
17391751
}
17401752

std/assembly/staticarray.ts

+130
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { OBJECT, BLOCK_MAXSIZE, TOTAL_OVERHEAD } from "./rt/common";
44
import { COMPARATOR, SORT } from "./util/sort";
5+
import { REVERSE } from "./util/bytes";
56
import { idof } from "./builtins";
67
import { Array } from "./array";
78
import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_HOLEYARRAY } from "./util/error";
@@ -137,6 +138,51 @@ export class StaticArray<T> {
137138
}
138139
}
139140

141+
fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
142+
var ptr = changetype<usize>(this);
143+
var len = this.length;
144+
start = start < 0 ? max(len + start, 0) : min(start, len);
145+
end = end < 0 ? max(len + end, 0) : min(end, len);
146+
if (isManaged<T>()) {
147+
for (; start < end; ++start) {
148+
store<usize>(ptr + (<usize>start << alignof<T>()), changetype<usize>(value));
149+
__link(changetype<usize>(this), changetype<usize>(value), true);
150+
}
151+
} else if (sizeof<T>() == 1) {
152+
if (start < end) {
153+
memory.fill(
154+
ptr + <usize>start,
155+
u8(value),
156+
<usize>(end - start)
157+
);
158+
}
159+
} else {
160+
for (; start < end; ++start) {
161+
store<T>(ptr + (<usize>start << alignof<T>()), value);
162+
}
163+
}
164+
return this;
165+
}
166+
167+
copyWithin(target: i32, start: i32, end: i32 = i32.MAX_VALUE): this {
168+
var ptr = changetype<usize>(this);
169+
var len = this.length;
170+
171+
end = min<i32>(end, len);
172+
173+
var to = target < 0 ? max(len + target, 0) : min(target, len);
174+
var from = start < 0 ? max(len + start, 0) : min(start, len);
175+
var last = end < 0 ? max(len + end, 0) : min(end, len);
176+
var count = min(last - from, len - to);
177+
178+
memory.copy( // is memmove
179+
ptr + (<usize>to << alignof<T>()),
180+
ptr + (<usize>from << alignof<T>()),
181+
<usize>count << alignof<T>()
182+
);
183+
return this;
184+
}
185+
140186
includes(value: T, fromIndex: i32 = 0): bool {
141187
if (isFloat<T>()) {
142188
let length = this.length;
@@ -230,6 +276,85 @@ export class StaticArray<T> {
230276
return slice;
231277
}
232278

279+
findIndex(fn: (value: T, index: i32, array: StaticArray<T>) => bool): i32 {
280+
for (let i = 0, len = this.length; i < len; ++i) {
281+
if (fn(load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this)) return i;
282+
}
283+
return -1;
284+
}
285+
286+
findLastIndex(fn: (value: T, index: i32, array: StaticArray<T>) => bool): i32 {
287+
for (let i = this.length - 1; i >= 0; --i) {
288+
if (fn(load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this)) return i;
289+
}
290+
return -1;
291+
}
292+
293+
forEach(fn: (value: T, index: i32, array: StaticArray<T>) => void): void {
294+
for (let i = 0, len = this.length; i < len; ++i) {
295+
fn(load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this);
296+
}
297+
}
298+
299+
map<U>(fn: (value: T, index: i32, array: StaticArray<T>) => U): Array<U> {
300+
var len = this.length;
301+
var out = changetype<Array<U>>(__newArray(len, alignof<U>(), idof<Array<U>>()));
302+
var outStart = out.dataStart;
303+
for (let i = 0; i < len; ++i) {
304+
let result = fn(load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this);
305+
store<U>(outStart + (<usize>i << alignof<U>()), result);
306+
if (isManaged<U>()) {
307+
__link(changetype<usize>(out), changetype<usize>(result), true);
308+
}
309+
}
310+
return out;
311+
}
312+
313+
filter(fn: (value: T, index: i32, array: StaticArray<T>) => bool): Array<T> {
314+
var result = changetype<Array<T>>(__newArray(0, alignof<T>(), idof<Array<T>>()));
315+
for (let i = 0, len = this.length; i < len; ++i) {
316+
let value = load<T>(changetype<usize>(this) + (<usize>i << alignof<T>()));
317+
if (fn(value, i, this)) result.push(value);
318+
}
319+
return result;
320+
}
321+
322+
reduce<U>(
323+
fn: (previousValue: U, currentValue: T, currentIndex: i32, array: StaticArray<T>) => U,
324+
initialValue: U
325+
): U {
326+
var acc = initialValue;
327+
for (let i = 0, len = this.length; i < len; ++i) {
328+
acc = fn(acc, load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this);
329+
}
330+
return acc;
331+
}
332+
333+
reduceRight<U>(
334+
fn: (previousValue: U, currentValue: T, currentIndex: i32, array: StaticArray<T>) => U,
335+
initialValue: U
336+
): U {
337+
var acc = initialValue;
338+
for (let i = this.length - 1; i >= 0; --i) {
339+
acc = fn(acc, load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this);
340+
}
341+
return acc;
342+
}
343+
344+
every(fn: (value: T, index: i32, array: StaticArray<T>) => bool): bool {
345+
for (let i = 0, len = this.length; i < len; ++i) {
346+
if (!fn(load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this)) return false;
347+
}
348+
return true;
349+
}
350+
351+
some(fn: (value: T, index: i32, array: StaticArray<T>) => bool): bool {
352+
for (let i = 0, len = this.length; i < len; ++i) {
353+
if (fn(load<T>(changetype<usize>(this) + (<usize>i << alignof<T>())), i, this)) return true;
354+
}
355+
return false;
356+
}
357+
233358
sort(comparator: (a: T, b: T) => i32 = COMPARATOR<T>()): this {
234359
SORT<T>(changetype<usize>(this), this.length, comparator);
235360
return this;
@@ -247,6 +372,11 @@ export class StaticArray<T> {
247372
return <string>unreachable();
248373
}
249374

375+
reverse(): this {
376+
REVERSE<T>(changetype<usize>(this), this.length);
377+
return this;
378+
}
379+
250380
toString(): string {
251381
return this.join();
252382
}

0 commit comments

Comments
 (0)