44 BoxMap as BoxMapType ,
55 BoxRef as BoxRefType ,
66 Box as BoxType ,
7- Bytes ,
87 bytes ,
98 GlobalStateOptions ,
109 GlobalState as GlobalStateType ,
@@ -17,7 +16,7 @@ import {
1716import { AccountMap } from '../collections/custom-key-map'
1817import { MAX_BOX_SIZE } from '../constants'
1918import { lazyContext } from '../context-helpers/internal-context'
20- import { asBytes , asNumber , toBytes } from '../util'
19+ import { asBytes , asBytesCls , asNumber , toBytes } from '../util'
2120
2221export class GlobalStateCls < ValueType > {
2322 private readonly _type : string = GlobalStateCls . name
@@ -272,7 +271,10 @@ export class BoxRefCls {
272271 }
273272
274273 get value ( ) : bytes {
275- return lazyContext . ledger . getBox ( this . #app, this . key )
274+ if ( ! this . exists ) {
275+ throw new internal . errors . InternalError ( 'Box has not been created' )
276+ }
277+ return toBytes ( this . backingValue )
276278 }
277279
278280 get exists ( ) : boolean {
@@ -284,14 +286,14 @@ export class BoxRefCls {
284286 if ( size > MAX_BOX_SIZE ) {
285287 throw new internal . errors . InternalError ( `Box size cannot exceed ${ MAX_BOX_SIZE } ` )
286288 }
287- const [ content , exists ] = this . maybe ( )
288- if ( exists && content . length !== size ) {
289+ const content = this . backingValue
290+ if ( this . exists && content . length !== size ) {
289291 throw new internal . errors . InternalError ( 'Box already exists with a different size' )
290292 }
291- if ( exists ) {
293+ if ( this . exists ) {
292294 return false
293295 }
294- lazyContext . ledger . setBox ( this . #app , this . key , Bytes ( Array ( size ) . fill ( 0 ) ) )
296+ this . backingValue = new Uint8Array ( Array ( size ) . fill ( 0 ) )
295297 return true
296298 }
297299
@@ -301,68 +303,69 @@ export class BoxRefCls {
301303 }
302304
303305 put ( value : internal . primitives . StubBytesCompat ) : void {
304- const bytesValue = asBytes ( value )
305- const [ content , exists ] = this . maybe ( )
306- if ( exists && content . length !== bytesValue . length ) {
306+ const bytesValue = asBytesCls ( value )
307+ const content = this . backingValue
308+ if ( this . exists && content . length !== bytesValue . length . asNumber ( ) ) {
307309 throw new internal . errors . InternalError ( 'Box already exists with a different size' )
308310 }
309- lazyContext . ledger . setBox ( this . #app , this . key , bytesValue )
311+ this . backingValue = bytesValue . asUint8Array ( )
310312 }
311313
312314 splice (
313315 start : internal . primitives . StubUint64Compat ,
314316 length : internal . primitives . StubUint64Compat ,
315317 value : internal . primitives . StubBytesCompat ,
316318 ) : void {
317- const [ content , exists ] = this . maybe ( )
319+ const content = this . backingValue
318320 const startNumber = asNumber ( start )
319321 const lengthNumber = asNumber ( length )
320- const valueBytes = asBytes ( value )
321- if ( ! exists ) {
322+ const valueBytes = asBytesCls ( value )
323+ if ( ! this . exists ) {
322324 throw new internal . errors . InternalError ( 'Box has not been created' )
323325 }
324326 if ( startNumber > content . length ) {
325327 throw new internal . errors . InternalError ( 'Start index exceeds box size' )
326328 }
327329 const end = Math . min ( startNumber + lengthNumber , content . length )
328- let updatedContent = content . slice ( 0 , startNumber ) . concat ( valueBytes ) . concat ( content . slice ( end ) )
330+ let updatedContent = this . concat ( content . slice ( 0 , startNumber ) , valueBytes . asUint8Array ( ) , content . slice ( end ) )
329331
330332 if ( updatedContent . length > content . length ) {
331333 updatedContent = updatedContent . slice ( 0 , content . length )
332334 } else if ( updatedContent . length < content . length ) {
333- updatedContent = updatedContent . concat ( Bytes ( Array ( content . length - updatedContent . length ) . fill ( 0 ) ) )
335+ updatedContent = this . concat ( updatedContent , new Uint8Array ( Array ( content . length - updatedContent . length ) . fill ( 0 ) ) )
334336 }
335- lazyContext . ledger . setBox ( this . #app , this . key , updatedContent )
337+ this . backingValue = updatedContent
336338 }
337339
338340 replace ( start : internal . primitives . StubUint64Compat , value : internal . primitives . StubBytesCompat ) : void {
339- const [ content , exists ] = this . maybe ( )
341+ const content = this . backingValue
340342 const startNumber = asNumber ( start )
341- const valueBytes = asBytes ( value )
342- if ( ! exists ) {
343+ const valueBytes = asBytesCls ( value )
344+ if ( ! this . exists ) {
343345 throw new internal . errors . InternalError ( 'Box has not been created' )
344346 }
345- if ( startNumber + valueBytes . length > content . length ) {
347+ if ( startNumber + asNumber ( valueBytes . length ) > content . length ) {
346348 throw new internal . errors . InternalError ( 'Replacement content exceeds box size' )
347349 }
348- const updatedContent = content
349- . slice ( 0 , startNumber )
350- . concat ( valueBytes )
351- . concat ( content . slice ( startNumber + valueBytes . length ) )
352- lazyContext . ledger . setBox ( this . #app, this . key , updatedContent )
350+ const updatedContent = this . concat (
351+ content . slice ( 0 , startNumber ) ,
352+ valueBytes . asUint8Array ( ) ,
353+ content . slice ( startNumber + valueBytes . length . asNumber ( ) ) ,
354+ )
355+ this . backingValue = updatedContent
353356 }
354357
355358 extract ( start : internal . primitives . StubUint64Compat , length : internal . primitives . StubUint64Compat ) : bytes {
356- const [ content , exists ] = this . maybe ( )
359+ const content = this . backingValue
357360 const startNumber = asNumber ( start )
358361 const lengthNumber = asNumber ( length )
359- if ( ! exists ) {
362+ if ( ! this . exists ) {
360363 throw new internal . errors . InternalError ( 'Box has not been created' )
361364 }
362365 if ( startNumber + lengthNumber > content . length ) {
363366 throw new internal . errors . InternalError ( 'Index out of bounds' )
364367 }
365- return content . slice ( startNumber , startNumber + lengthNumber )
368+ return toBytes ( content . slice ( startNumber , startNumber + lengthNumber ) )
366369 }
367370 delete ( ) : boolean {
368371 return lazyContext . ledger . deleteBox ( this . #app, this . key )
@@ -373,29 +376,46 @@ export class BoxRefCls {
373376 if ( newSizeNumber > MAX_BOX_SIZE ) {
374377 throw new internal . errors . InternalError ( `Box size cannot exceed ${ MAX_BOX_SIZE } ` )
375378 }
376- const [ content , exists ] = this . maybe ( )
377- if ( ! exists ) {
379+ const content = this . backingValue
380+ if ( ! this . exists ) {
378381 throw new internal . errors . InternalError ( 'Box has not been created' )
379382 }
380383 let updatedContent
381384 if ( newSizeNumber > content . length ) {
382- updatedContent = content . concat ( Bytes ( Array ( newSizeNumber - content . length ) . fill ( 0 ) ) )
385+ updatedContent = this . concat ( content , new Uint8Array ( Array ( newSizeNumber - content . length ) . fill ( 0 ) ) )
383386 } else {
384387 updatedContent = content . slice ( 0 , newSize )
385388 }
386- lazyContext . ledger . setBox ( this . #app , this . key , updatedContent )
389+ this . backingValue = updatedContent
387390 }
388391
389392 maybe ( ) : readonly [ bytes , boolean ] {
390- return [ lazyContext . ledger . getBox ( this . #app, this . key ) , lazyContext . ledger . boxExists ( this . #app, this . key ) ]
393+ return [ asBytes ( lazyContext . ledger . getBox ( this . #app, this . key ) ) , lazyContext . ledger . boxExists ( this . #app, this . key ) ]
391394 }
392395
393396 get length ( ) : uint64 {
394- const [ value , exists ] = this . maybe ( )
395- if ( ! exists ) {
397+ if ( ! this . exists ) {
396398 throw new internal . errors . InternalError ( 'Box has not been created' )
397399 }
398- return value . length
400+ return this . backingValue . length
401+ }
402+
403+ private get backingValue ( ) : Uint8Array {
404+ return lazyContext . ledger . getBox ( this . #app, this . key )
405+ }
406+
407+ private set backingValue ( value : Uint8Array ) {
408+ lazyContext . ledger . setBox ( this . #app, this . key , value )
409+ }
410+
411+ private concat ( ...values : Uint8Array [ ] ) : Uint8Array {
412+ const result = new Uint8Array ( values . reduce ( ( acc , value ) => acc + value . length , 0 ) )
413+ let index = 0
414+ for ( const value of values ) {
415+ result . set ( value , index )
416+ index += value . length
417+ }
418+ return result
399419 }
400420}
401421
0 commit comments