@@ -35,7 +35,17 @@ import { lazyContext } from '../context-helpers/internal-context'
3535import type { fromBytes , TypeInfo } from '../encoders'
3636import { AvmError , avmInvariant , CodeError } from '../errors'
3737import type { DeliberateAny } from '../typescript-helpers'
38- import { asBigInt , asBigUint , asBigUintCls , asBytesCls , asUint64 , asUint8Array , conactUint8Arrays , uint8ArrayToNumber } from '../util'
38+ import {
39+ asBigInt ,
40+ asBigUint ,
41+ asBigUintCls ,
42+ asBytes ,
43+ asBytesCls ,
44+ asUint64 ,
45+ asUint8Array ,
46+ conactUint8Arrays ,
47+ uint8ArrayToNumber ,
48+ } from '../util'
3949import type { StubBytesCompat } from './primitives'
4050import { AlgoTsPrimitiveCls , arrayUtil , BigUintCls , Bytes , BytesCls , getUint8Array , isBytes , Uint64Cls } from './primitives'
4151import { Account , AccountCls , ApplicationCls , AssetCls } from './reference'
@@ -46,7 +56,8 @@ const maxBigIntValue = (bitSize: number) => 2n ** BigInt(bitSize) - 1n
4656const maxBytesLength = ( bitSize : number ) => Math . floor ( bitSize / BITS_IN_BYTE )
4757const encodeLength = ( length : number ) => new BytesCls ( encodingUtil . bigIntToUint8Array ( BigInt ( length ) , ABI_LENGTH_SIZE ) )
4858
49- type CompatForArc4Int < N extends BitSize > = N extends 8 | 16 | 32 | 64 ? Uint64Compat : BigUintCompat
59+ type CompatForArc4Int < N extends BitSize > = N extends 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 ? Uint64Compat : BigUintCompat
60+ const validBitSizes = [ ...Array ( 64 ) . keys ( ) ] . map ( ( x ) => ( x + 1 ) * 8 )
5061export class UintNImpl < N extends BitSize > extends UintN < N > {
5162 private value : Uint8Array
5263 private bitSize : N
@@ -57,7 +68,7 @@ export class UintNImpl<N extends BitSize> extends UintN<N> {
5768 this . typeInfo = typeof typeInfo === 'string' ? JSON . parse ( typeInfo ) : typeInfo
5869 this . bitSize = UintNImpl . getMaxBitsLength ( this . typeInfo ) as N
5970
60- assert ( [ 8 , 16 , 32 , 64 , 128 , 256 , 512 ] . includes ( this . bitSize ) , `Invalid bit size ${ this . bitSize } ` )
71+ assert ( validBitSizes . includes ( this . bitSize ) , `Invalid bit size ${ this . bitSize } ` )
6172
6273 const bigIntValue = asBigUintCls ( v ?? 0n ) . valueOf ( )
6374 const maxValue = maxBigIntValue ( this . bitSize )
@@ -299,7 +310,7 @@ const arrayProxyHandler = <TItem>() => ({
299310 get ( target : { items : TItem [ ] } , prop : PropertyKey ) {
300311 const idx = prop ? parseInt ( prop . toString ( ) , 10 ) : NaN
301312 if ( ! isNaN ( idx ) ) {
302- if ( idx < target . items . length ) return target . items [ idx ]
313+ if ( idx >= 0 && idx < target . items . length ) return target . items [ idx ]
303314 throw new AvmError ( 'Index out of bounds' )
304315 } else if ( prop === Symbol . iterator ) {
305316 return target . items [ Symbol . iterator ] . bind ( target . items )
@@ -315,7 +326,7 @@ const arrayProxyHandler = <TItem>() => ({
315326 set ( target : { items : TItem [ ] ; setItem : ( index : number , value : TItem ) => void } , prop : PropertyKey , value : TItem ) {
316327 const idx = prop ? parseInt ( prop . toString ( ) , 10 ) : NaN
317328 if ( ! isNaN ( idx ) ) {
318- if ( idx < target . items . length ) {
329+ if ( idx >= 0 && idx < target . items . length ) {
319330 target . setItem ( idx , value )
320331 return true
321332 }
@@ -391,6 +402,20 @@ export class StaticArrayImpl<TItem extends ARC4Encoded, TLength extends number>
391402 return StaticArrayImpl . fromBytesImpl ( this . bytes , JSON . stringify ( this . typeInfo ) ) as StaticArrayImpl < TItem , TLength >
392403 }
393404
405+ concat ( other : Parameters < InstanceType < typeof StaticArray > [ 'concat' ] > [ 0 ] ) : DynamicArrayImpl < TItem > {
406+ const items = this . items
407+ const otherEntries = other . entries ( )
408+ let next = otherEntries . next ( )
409+ while ( ! next . done ) {
410+ items . push ( next . value [ 1 ] as TItem )
411+ next = otherEntries . next ( )
412+ }
413+ return new DynamicArrayImpl < TItem > (
414+ { name : `DynamicArray<${ this . genericArgs . elementType . name } >` , genericArgs : { elementType : this . genericArgs . elementType } } ,
415+ ...items ,
416+ )
417+ }
418+
394419 get native ( ) : TItem [ ] {
395420 return this . items
396421 }
@@ -578,6 +603,17 @@ export class DynamicArrayImpl<TItem extends ARC4Encoded> extends DynamicArray<TI
578603 return popped
579604 }
580605
606+ concat ( other : Parameters < InstanceType < typeof DynamicArray > [ 'concat' ] > [ 0 ] ) : DynamicArrayImpl < TItem > {
607+ const items = this . items
608+ const otherEntries = other . entries ( )
609+ let next = otherEntries . next ( )
610+ while ( ! next . done ) {
611+ items . push ( next . value [ 1 ] as TItem )
612+ next = otherEntries . next ( )
613+ }
614+ return new DynamicArrayImpl < TItem > ( this . typeInfo , ...items )
615+ }
616+
581617 static fromBytesImpl (
582618 value : StubBytesCompat | Uint8Array ,
583619 typeInfo : string | TypeInfo ,
@@ -822,6 +858,20 @@ export class DynamicBytesImpl extends DynamicBytes {
822858 throw new CodeError ( 'DynamicBytes is immutable' )
823859 }
824860
861+ concat ( other : Parameters < InstanceType < typeof DynamicBytes > [ 'concat' ] > [ 0 ] ) : DynamicBytesImpl {
862+ const items = this . items
863+ const otherEntries = other . entries ( )
864+ let next = otherEntries . next ( )
865+ while ( ! next . done ) {
866+ items . push ( next . value [ 1 ] as ByteImpl )
867+ next = otherEntries . next ( )
868+ }
869+ const concatenatedBytes = items
870+ . map ( ( item ) => item . bytes )
871+ . reduce ( ( acc , curr ) => conactUint8Arrays ( acc , asUint8Array ( curr ) ) , new Uint8Array ( ) )
872+ return new DynamicBytesImpl ( this . typeInfo , asBytes ( concatenatedBytes ) )
873+ }
874+
825875 static fromBytesImpl (
826876 value : StubBytesCompat | Uint8Array ,
827877 typeInfo : string | TypeInfo ,
@@ -877,6 +927,20 @@ export class StaticBytesImpl extends StaticBytes {
877927 throw new CodeError ( 'StaticBytes is immutable' )
878928 }
879929
930+ concat ( other : Parameters < InstanceType < typeof StaticBytes > [ 'concat' ] > [ 0 ] ) : DynamicBytesImpl {
931+ const items = this . items
932+ const otherEntries = other . entries ( )
933+ let next = otherEntries . next ( )
934+ while ( ! next . done ) {
935+ items . push ( next . value [ 1 ] as ByteImpl )
936+ next = otherEntries . next ( )
937+ }
938+ const concatenatedBytes = items
939+ . map ( ( item ) => item . bytes )
940+ . reduce ( ( acc , curr ) => conactUint8Arrays ( acc , asUint8Array ( curr ) ) , new Uint8Array ( ) )
941+ return new DynamicBytesImpl ( this . typeInfo , asBytes ( concatenatedBytes ) )
942+ }
943+
880944 static fromBytesImpl ( value : StubBytesCompat | Uint8Array , typeInfo : string | TypeInfo , prefix : 'none' | 'log' = 'none' ) : StaticBytesImpl {
881945 const staticArrayValue = StaticArrayImpl . fromBytesImpl ( value , typeInfo , prefix ) as StaticArrayImpl < ByteImpl , number >
882946 const result = new StaticBytesImpl ( typeInfo )
0 commit comments