author jdiaz5513
  import initTrace from "debug" ; import { PTR_COMPOSITE_SIZE_UNDEFINED , PTR_INVALID_LIST_SIZE } from "../../errors" ; import { format , identity } from "../../util" ; import { ListElementSize } from "../list-element-size" ; import { ObjectSize , padToWord , getByteLength } from "../object-size" ; import { Segment } from "../segment" ; import { Pointer , getTargetListLength , getListElementByteLength , setStructPointer , setListPointer , initPointer , } from "./pointer" ; const trace = initTrace ( "capnp:list" ) ; trace ( "load" ) ; export interface _ListCtor { readonly compositeSize ? : ObjectSize ; readonly displayName : string ; readonly size : ListElementSize ; } export interface ListCtor < T > { readonly _capnp : _ListCtor ; new ( segment , byteOffset , depthLimit ? ) : List < T > ; } export type FilterCallback < T > = ( this : void , value : T , index : number ) => boolean ; export type IndexedCallback < T , U > = ( this : void , value : T , index : number ) => U ; export interface Group < T > { [ k ] : T ; } /**
 * A generic list class. Implements Filterable,
 */ export class List < T > extends Pointer { static readonly _capnp : _ListCtor = { displayName : "List<Generic>" as string , size : ListElementSize . VOID , } ; static readonly get = get ; static readonly initList = initList ; static readonly set = set ; static toString ( ) { return this . _capnp . displayName ; } all ( callbackfn ) { const length = this . getLength ( ) ; for ( let i = 0 ; i < length ; i ++ ) { if ( ! callbackfn ( this . get ( i ) , i ) ) return false ; } return true ; } any ( callbackfn ) { const length = this . getLength ( ) ; for ( let i = 0 ; i < length ; i ++ ) { if ( callbackfn ( this . get ( i ) , i ) ) return true ; } return false ; } ap < U > ( callbackfns ) { const length = this . getLength ( ) ; const res = [ ] ; for ( let i = 0 ; i < length ; i ++ ) { res . push ( ... callbackfns . map ( ( f ) => f ( this . get ( i ) , i ) ) ) ; } return res ; } concat ( other ) { const length = this . getLength ( ) ; const otherLength = other . getLength ( ) ; const res = new Array < T > ( length + otherLength ) ; for ( let i = 0 ; i < length ; i ++ ) res [ i ] = this . get ( i ) ; for ( let i = 0 ; i < otherLength ; i ++ ) res [ i + length ] = other . get ( i ) ; return res ; } drop ( n ) { const length = this . getLength ( ) ; const res = new Array ( length ) as T [ ] ; for ( let i = n ; i < length ; i ++ ) res [ i ] = this . get ( i ) ; return res ; } dropWhile ( callbackfn ) { const length = this . getLength ( ) ; const res = [ ] ; let drop = true ; for ( let i = 0 ; i < length ; i ++ ) { const v = this . get ( i ) ; if ( drop ) drop = callbackfn ( v , i ) ; if ( ! drop ) res . push ( v ) ; } return res ; } empty ( ) { return [ ] as T [ ] ; } every ( callbackfn ) { return this . all ( callbackfn ) ; } filter ( callbackfn ) { const length = this . getLength ( ) ; const res = [ ] ; for ( let i = 0 ; i < length ; i ++ ) { const value = this . get ( i ) ; if ( callbackfn ( value , i ) ) res . push ( value ) ; } return res ; } find ( callbackfn ) { const length = this . getLength ( ) ; for ( let i = 0 ; i < length ; i ++ ) { const value = this . get ( i ) ; if ( callbackfn ( value , i ) ) return value ; } return undefined ; } findIndex ( callbackfn ) { const length = this . getLength ( ) ; for ( let i = 0 ; i < length ; i ++ ) { const value = this . get ( i ) ; if ( callbackfn ( value , i ) ) return i ; } return - 1 ; } forEach ( callbackfn ) { const length = this . getLength ( ) ; for ( let i = 0 ; i < length ; i ++ ) callbackfn ( this . get ( i ) , i ) ; } get ( _index ) { return get ( _index , this ) ; } returns { number } getLength ( ) { return getTargetListLength ( this ) ; } groupBy ( callbackfn ) { const length = this . getLength ( ) ; const res = { } ; for ( let i = 0 ; i < length ; i ++ ) { const v = this . get ( i ) ; res [ callbackfn ( v , i ) ] = v ; } return res ; } intersperse ( sep ) { const length = this . getLength ( ) ; const res = new Array ( length ) as T [ ] ; for ( let i = 0 ; i < length ; i ++ ) { if ( i > 0 ) res . push ( sep ) ; res . push ( this . get ( i ) ) ; } return res ; } map < U > ( callbackfn ) { const length = this . getLength ( ) ; const res = new Array ( length ) as U [ ] ; for ( let i = 0 ; i < length ; i ++ ) res [ i ] = callbackfn ( this . get ( i ) , i ) ; return res ; } reduce ( callbackfn ) ; reduce < U > ( callbackfn , initialValue ) ; reduce < U > ( callbackfn , initialValue ? ) { let i = 0 ; let res ; if ( initialValue === undefined ) { res = this . get ( 0 ) ; i ++ ; } else { res = initialValue ; } for ( ; i < this . getLength ( ) ; i ++ ) res = callbackfn ( res , this . get ( i ) , i ) ; return res ; } set ( _index , _value ) { set ( _index , _value , this ) ; } slice ( start = 0 , end ? ) { const length = end ? Math . min ( this . getLength ( ) , end ) : this . getLength ( ) ; const res = new Array ( length - start ) as T [ ] ; for ( let i = start ; i < length ; i ++ ) res [ i ] = this . get ( i ) ; return res ; } some ( callbackfn ) { return this . any ( callbackfn ) ; } take ( n ) { const length = Math . min ( this . getLength ( ) , n ) ; const res = new Array ( length ) as T [ ] ; for ( let i = 0 ; i < length ; i ++ ) res [ i ] = this . get ( i ) ; return res ; } takeWhile ( callbackfn ) { const length = this . getLength ( ) ; const res = [ ] ; let take ; for ( let i = 0 ; i < length ; i ++ ) { const v = this . get ( i ) ; take = callbackfn ( v , i ) ; if ( ! take ) return res ; res . push ( v ) ; } return res ; } toArray ( ) { return this . map ( identity ) ; } toString ( ) { return `List_${ super . toString ( ) }` ; } } param { ListElementSize } elementSize param { number } length param { List < T > } l param { ObjectSize } compositeSize returns { void } export function initList < T > ( elementSize , length , l , compositeSize ? ) { let c ; switch ( elementSize ) { case ListElementSize . BIT : c = l . segment . allocate ( Math . ceil ( length / 8 ) ) ; break ; case ListElementSize . BYTE : case ListElementSize . BYTE_2 : case ListElementSize . BYTE_4 : case ListElementSize . BYTE_8 : case ListElementSize . POINTER : c = l . segment . allocate ( length * getListElementByteLength ( elementSize ) ) ; break ; case ListElementSize . COMPOSITE : { if ( compositeSize === undefined ) { throw new Error ( format ( PTR_COMPOSITE_SIZE_UNDEFINED ) ) ; } compositeSize = padToWord ( compositeSize ) ; const byteLength = getByteLength ( compositeSize ) * length ; c = l . segment . allocate ( byteLength + 8 ) ; setStructPointer ( length , compositeSize , c ) ; trace ( "Wrote composite tag word %s for %s." , c , l ) ; break ; } case ListElementSize . VOID : setListPointer ( 0 , elementSize , length , l ) ; return ; default : throw new Error ( format ( PTR_INVALID_LIST_SIZE , elementSize ) ) ; } const res = initPointer ( c . segment , c . byteOffset , l ) ; setListPointer ( res . offsetWords , elementSize , length , res . pointer , compositeSize ) ; } export function get < T > ( _index , _l ) { throw new TypeError ( ) ; } export function set < T > ( _index , _value , _l ) { throw new TypeError ( ) ; }