github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/evm/emulator/state/code.go (about) 1 package state 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 ) 7 8 // CodeContainer contains codes and keeps 9 // track of reference counts 10 type CodeContainer struct { 11 code []byte 12 // keeping encoded so we can reuse it later 13 buffer []byte 14 refCount uint64 15 } 16 17 // NewCodeContainer constructs a new code container 18 func NewCodeContainer(code []byte) *CodeContainer { 19 return &CodeContainer{ 20 code: code, 21 refCount: 1, 22 } 23 } 24 25 // CodeContainerFromEncoded constructs a code container from the encoded data 26 func CodeContainerFromEncoded(encoded []byte) (*CodeContainer, error) { 27 if len(encoded) < 8 { 28 return nil, fmt.Errorf("invalid length for the encoded code container") 29 } 30 return &CodeContainer{ 31 refCount: binary.BigEndian.Uint64(encoded[:8]), 32 buffer: encoded, // keep encoded as buffer for future use 33 code: encoded[8:], 34 }, nil 35 } 36 37 // Code returns the code part of the code container 38 func (cc *CodeContainer) Code() []byte { 39 return cc.code 40 } 41 42 // RefCount returns the ref count 43 func (cc *CodeContainer) RefCount() uint64 { 44 return cc.refCount 45 } 46 47 // IncRefCount increment the ref count 48 func (cc *CodeContainer) IncRefCount() { 49 cc.refCount++ 50 } 51 52 // DecRefCount decrement the ref count and 53 // returns true if the ref has reached to zero 54 func (cc *CodeContainer) DecRefCount() bool { 55 // check if ref is already zero 56 // this condition should never happen 57 // but better to be here to prevent underflow 58 if cc.refCount == 0 { 59 return true 60 } 61 cc.refCount-- 62 return cc.refCount == 0 63 } 64 65 // Encoded returns the encoded content of the code container 66 func (cc *CodeContainer) Encode() []byte { 67 // try using the buffer if possible to avoid 68 // extra allocations 69 encodedLen := 8 + len(cc.code) 70 var encoded []byte 71 if len(cc.buffer) < encodedLen { 72 encoded = make([]byte, encodedLen) 73 } else { 74 encoded = cc.buffer[:encodedLen] 75 } 76 binary.BigEndian.PutUint64(encoded[:8], cc.refCount) 77 copy(encoded[8:], cc.code) 78 return encoded 79 }