@@ -493,6 +493,64 @@ export class Array<T> {
493
493
return < string > unreachable ( ) ;
494
494
}
495
495
496
+ flat ( ) : T {
497
+ if ( ! isArray < T > ( ) ) {
498
+ ERROR ( "Cannot call flat() on Array<T> where T is not an Array." ) ;
499
+ }
500
+ // Get the length and data start values
501
+ var length = this . length_ ;
502
+ var selfDataStart = this . dataStart ;
503
+
504
+ // calculate the end size with an initial pass
505
+ var size = 0 ;
506
+ for ( let i = 0 ; i < length ; i ++ ) {
507
+ let child = load < usize > ( selfDataStart + ( i << alignof < T > ( ) ) ) ;
508
+ size += child == 0 ? 0 : load < i32 > ( child , offsetof < T > ( "length_" ) ) ;
509
+ }
510
+
511
+ // calculate the byteLength of the resulting backing ArrayBuffer
512
+ var byteLength = < usize > size << usize ( alignof < valueof < T > > ( ) ) ;
513
+ var dataStart = __alloc ( byteLength , idof < ArrayBuffer > ( ) ) ;
514
+
515
+ // create the return value and initialize it
516
+ var result = __alloc ( offsetof < T > ( ) , idof < T > ( ) ) ;
517
+ store < i32 > ( result , size , offsetof < T > ( "length_" ) ) ;
518
+
519
+ // byteLength, dataStart, and buffer are all readonly
520
+ store < i32 > ( result , byteLength , offsetof < T > ( "byteLength" ) ) ;
521
+ store < usize > ( result , dataStart , offsetof < T > ( "dataStart" ) ) ;
522
+ store < usize > ( result , __retain ( dataStart ) , offsetof < T > ( "buffer" ) ) ;
523
+
524
+ // set the elements
525
+ var resultOffset : usize = 0 ;
526
+ for ( let i = 0 ; i < length ; i ++ ) { // for each child
527
+ let child = load < usize > ( selfDataStart + ( < usize > i << alignof < T > ( ) ) ) ;
528
+
529
+ // ignore null arrays
530
+ if ( child == 0 ) continue ;
531
+
532
+ // copy the underlying buffer data to the result buffer
533
+ let childDataLength = load < i32 > ( child , offsetof < T > ( "byteLength" ) ) ;
534
+ memory . copy (
535
+ dataStart + resultOffset ,
536
+ load < usize > ( child , offsetof < T > ( "dataStart" ) ) ,
537
+ < usize > childDataLength
538
+ ) ;
539
+
540
+ // advance the result length
541
+ resultOffset += childDataLength ;
542
+ }
543
+
544
+ // if the `valueof<T>` type is managed, we must call __retain() on each reference
545
+ if ( isManaged < valueof < T > > ( ) ) {
546
+ for ( let i = 0 ; i < size ; i ++ ) {
547
+ __retain ( load < usize > ( dataStart + ( < usize > i << usize ( alignof < valueof < T > > ( ) ) ) ) ) ;
548
+ }
549
+ }
550
+
551
+ return changetype < T > ( result ) ;
552
+ }
553
+
496
554
toString ( ) : string {
497
555
return this . join ( ) ;
498
556
}
0 commit comments