author liangqin.fan gmail import { Codec , Int32 , UInt32 , Hash , ScaleString } from ".." ; import { ReturnCode } from "../primitives/alias" ; import { Crypto } from "../primitives/crypto" ; import { ArrayEntry } from "./ArrayEntry" ; import { Storage } from "./storage" ; export abstract class StorableArray < T extends Codec > implements Codec { [ key ] : T ; protected keyPrefix : string ; protected arrayInner : Array < T > ; abstract pushValue ( value ) ; abstract popValue ( ) ; abstract setValueAt ( index , value ) ; abstract deleteValueAt ( index ) ; abstract visitValueAt ( index ) ; abstract storeItemsFrom ( index ) ; abstract loadItemsFrom ( index ) ; constructor ( prefix = "" , capacity = 0 ) { this . keyPrefix = prefix ; this . arrayInner = new Array < T > ( capacity ) ; } toU8a ( ) { return ( new ScaleString ( this . keyPrefix ) ) . toU8a ( ) ; } encodedLength ( ) { return ( new ScaleString ( this . keyPrefix ) ) . encodedLength ( ) ; } populateFromBytes ( bytes , index ) { let s = new ScaleString ( ) ; s . populateFromBytes ( bytes , index ) ; this . keyPrefix = s . toString ( ) ; } eq ( other ) { return this . keyPrefix == other . keyPrefix ; } notEq ( other ) { return ! this . eq ( other ) ; } protected loadArrayEntry ( ) { let strg = new Storage ( Crypto . blake256s ( this . keyPrefix + ".length" ) ) ; let entryInfo = strg . load < ArrayEntry > ( ) ; return entryInfo ; } protected storeArrayEntry ( storedBytes = 0 ) { let entryHash = Crypto . blake256s ( this . keyPrefix + ".length" ) ; let strg = new Storage ( entryHash ) ; let v = new ArrayEntry ( this . arrayInner . length , storedBytes ) ; let r = strg . store ( v ) ; return r ; } protected indexToHashKey ( index ) { return Crypto . blake256s ( this . keyPrefix + index . toString ( ) ) ; } get length ( ) : i32 { return this . arrayInner . length ; } get entryKey ( ) : string { return this . keyPrefix ; } set entryKey ( str ) { this . keyPrefix = str ; } @ operator ( "[]" ) private __get ( index ) { return this . at ( index ) ; } @ operator ( "[]=" ) private __set ( index , value ) { this . setValueAt ( index , value ) ; } push ( value ) { return this . pushValue ( value ) ; } pop ( ) { return this . popValue ( ) ; } delete ( index ) { return this . deleteValueAt ( index ) ; } at ( index ) { assert ( index < this . arrayInner . length , "out of bounds" ) ; return this . visitValueAt ( index ) ; } fill ( value , start = 0 , end = i32 . MAX_VALUE ) { this . arrayInner . fill ( value , start , end ) ; this . storeItemsFrom ( start ) ; return this ; } every ( callbackfn ) { for ( let i = 0 ; i < this . arrayInner . length ; i ++ ) { let v = this . at ( i ) ; if ( ! callbackfn ( v , i , this . arrayInner ) ) return false ; } return true ; } findIndex ( predicate ) { let index = this . arrayInner . findIndex ( predicate ) ; if ( index != - 1 ) return index ; for ( let i = 0 ; i < this . arrayInner . length ; i ++ ) { let v = this . at ( i ) ; if ( predicate ( v , i , this . arrayInner ) ) return i ; } return - 1 ; } includes ( searchElement , fromIndex = 0 ) { return this . indexOf ( searchElement , fromIndex ) >= 0 ; } indexOf ( searchElement , fromIndex = 0 ) { let index = this . arrayInner . indexOf ( searchElement , fromIndex ) ; if ( index != - 1 ) return index ; for ( let i = fromIndex ; i < this . arrayInner . length ; i ++ ) { if ( this . at ( i ) . eq ( searchElement ) ) return i ; } return - 1 ; } lastIndexOf ( searchElement , fromIndex = 0 ) { let index = this . arrayInner . lastIndexOf ( searchElement , fromIndex ) ; if ( index != - 1 ) return index ; let length = this . arrayInner . length ; if ( length == 0 ) return - 1 ; if ( fromIndex < 0 ) fromIndex = length + fromIndex ; else if ( fromIndex >= length ) fromIndex = length - 1 ; while ( fromIndex >= 0 ) { let v = this . at ( fromIndex ) ; if ( v . eq ( searchElement ) ) return fromIndex ; -- fromIndex ; } return - 1 ; } concat ( items ) { let oldlen = this . arrayInner . length ; this . arrayInner = this . arrayInner . concat ( items ) ; this . storeItemsFrom ( oldlen ) ; return this . arrayInner ; } forEach ( callbackfn ) { for ( let i = 0 ; i < this . arrayInner . length ; i ++ ) { let v = this . at ( i ) ; callbackfn ( v , i , this . arrayInner ) ; } } map < U > ( callbackfn ) { let uarr = new Array < U > ( this . arrayInner . length ) ; for ( let i = 0 ; i < this . arrayInner . length ; i ++ ) { let v = this . at ( i ) ; let mv = callbackfn ( v , i , this . arrayInner ) ; uarr . push ( mv ) ; } return uarr ; } filter ( callbackfn ) { let uarr = new Array < T > ( ) ; for ( let i = 0 ; i < this . arrayInner . length ; i ++ ) { let v = this . at ( i ) ; if ( callbackfn ( v , i , this . arrayInner ) ) { uarr . push ( v ) ; } } return uarr ; } reduce < U > ( callbackfn , initialValue ) { return this . arrayInner . reduce < U > ( callbackfn , initialValue ) ; } reduceRight < U > ( callbackfn , initialValue ) { return this . arrayInner . reduceRight < U > ( callbackfn , initialValue ) ; } some ( callbackfn ) { for ( let i = 0 ; i < this . arrayInner . length ; i ++ ) { let v = this . at ( i ) ; if ( callbackfn ( v , i , this . arrayInner ) ) return true ; } return false ; } slice ( from , to = i32 . MAX_VALUE ) { return this . arrayInner . slice ( from , to ) ; } splice ( start , deleteCount = i32 . MAX_VALUE ) { return this . arrayInner . splice ( start , deleteCount ) ; } sort ( comparator ) { this . loadItemsFrom ( 0 ) ; this . arrayInner = this . arrayInner . sort ( comparator ) ; this . storeItemsFrom ( 0 ) ; return this ; } reverse ( ) { this . loadItemsFrom ( 0 ) ; this . arrayInner = this . arrayInner . reverse ( ) ; this . storeItemsFrom ( 0 ) ; return this . arrayInner ; } }