github.com/datachainlab/burrow@v0.25.0/execution/evm/asm/bc/helpers.go (about)

     1  package bc
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hyperledger/burrow/execution/evm/asm"
     7  )
     8  
     9  type ByteSlicable interface {
    10  	Bytes() []byte
    11  }
    12  
    13  // Concatenate multiple byte slices without unnecessary copying
    14  func Concat(bss ...[]byte) []byte {
    15  	offset := 0
    16  	for _, bs := range bss {
    17  		offset += len(bs)
    18  	}
    19  	bytes := make([]byte, offset)
    20  	offset = 0
    21  	for _, bs := range bss {
    22  		for i, b := range bs {
    23  			bytes[offset+i] = b
    24  		}
    25  		offset += len(bs)
    26  	}
    27  	return bytes
    28  }
    29  
    30  // Splice or panic
    31  func MustSplice(bytelikes ...interface{}) []byte {
    32  	spliced, err := Splice(bytelikes...)
    33  	if err != nil {
    34  		panic(err)
    35  	}
    36  	return spliced
    37  }
    38  
    39  // Convenience function to allow us to mix bytes, ints, and OpCodes that
    40  // represent bytes in an EVM assembly code to make assembly more readable.
    41  // Also allows us to splice together assembly
    42  // fragments because any []byte arguments are flattened in the result.
    43  func Splice(bytelikes ...interface{}) ([]byte, error) {
    44  	bytes := make([]byte, 0, len(bytelikes))
    45  	for _, bytelike := range bytelikes {
    46  		bs, err := byteSlicify(bytelike)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  		bytes = append(bytes, bs...)
    51  	}
    52  	return bytes, nil
    53  }
    54  
    55  // Convert anything byte or byte slice like to a byte slice
    56  func byteSlicify(bytelike interface{}) ([]byte, error) {
    57  	switch b := bytelike.(type) {
    58  	case byte:
    59  		return []byte{b}, nil
    60  	case asm.OpCode:
    61  		return []byte{byte(b)}, nil
    62  	case int:
    63  		if int(byte(b)) != b {
    64  			return nil, fmt.Errorf("the int %v does not fit inside a byte", b)
    65  		}
    66  		return []byte{byte(b)}, nil
    67  	case int64:
    68  		if int64(byte(b)) != b {
    69  			return nil, fmt.Errorf("the int64 %v does not fit inside a byte", b)
    70  		}
    71  		return []byte{byte(b)}, nil
    72  	case uint64:
    73  		if uint64(byte(b)) != b {
    74  			return nil, fmt.Errorf("the uint64 %v does not fit inside a byte", b)
    75  		}
    76  		return []byte{byte(b)}, nil
    77  	case string:
    78  		return []byte(b), nil
    79  	case ByteSlicable:
    80  		return b.Bytes(), nil
    81  	case []byte:
    82  		return b, nil
    83  	default:
    84  		return nil, fmt.Errorf("could not convert %s to a byte or sequence of bytes", bytelike)
    85  	}
    86  }