@@ -493,6 +493,64 @@ export class Array<T> {
493493 return < string > unreachable ( ) ;
494494 }
495495
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+
496554 toString ( ) : string {
497555 return this . join ( ) ;
498556 }
0 commit comments