bytes.go 3.07 KB
Newer Older
obscuren's avatar
obscuren committed
1 2 3 4 5
package ethutil

import (
	"bytes"
	"encoding/binary"
6
	"encoding/hex"
obscuren's avatar
obscuren committed
7
	"fmt"
obscuren's avatar
obscuren committed
8
	"math/big"
9
	"strings"
obscuren's avatar
obscuren committed
10 11
)

12 13 14
// Number to bytes
//
// Returns the number in bytes with the specified base
obscuren's avatar
obscuren committed
15 16 17 18 19 20 21 22 23 24
func NumberToBytes(num interface{}, bits int) []byte {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.BigEndian, num)
	if err != nil {
		fmt.Println("NumberToBytes failed:", err)
	}

	return buf.Bytes()[buf.Len()-(bits/8):]
}

25 26 27
// Bytes to number
//
// Attempts to cast a byte slice to a unsigned integer
obscuren's avatar
obscuren committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
func BytesToNumber(b []byte) uint64 {
	var number uint64

	// Make sure the buffer is 64bits
	data := make([]byte, 8)
	data = append(data[:len(b)], b...)

	buf := bytes.NewReader(data)
	err := binary.Read(buf, binary.BigEndian, &number)
	if err != nil {
		fmt.Println("BytesToNumber failed:", err)
	}

	return number
}

44 45 46
// Read variable int
//
// Read a variable length number in big endian byte order
obscuren's avatar
obscuren committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
func ReadVarint(reader *bytes.Reader) (ret uint64) {
	if reader.Len() == 8 {
		var num uint64
		binary.Read(reader, binary.BigEndian, &num)
		ret = uint64(num)
	} else if reader.Len() == 4 {
		var num uint32
		binary.Read(reader, binary.BigEndian, &num)
		ret = uint64(num)
	} else if reader.Len() == 2 {
		var num uint16
		binary.Read(reader, binary.BigEndian, &num)
		ret = uint64(num)
	} else {
		var num uint8
		binary.Read(reader, binary.BigEndian, &num)
		ret = uint64(num)
	}

	return ret
}

69 70 71
// Binary length
//
// Returns the true binary length of the given number
obscuren's avatar
obscuren committed
72 73 74 75 76 77 78
func BinaryLength(num int) int {
	if num == 0 {
		return 0
	}

	return 1 + BinaryLength(num>>8)
}
obscuren's avatar
obscuren committed
79 80 81 82 83 84 85 86 87 88

// Copy bytes
//
// Returns an exact copy of the provided bytes
func CopyBytes(b []byte) (copiedBytes []byte) {
	copiedBytes = make([]byte, len(b))
	copy(copiedBytes, b)

	return
}
89 90 91 92 93

func IsHex(str string) bool {
	l := len(str)
	return l >= 4 && l%2 == 0 && str[0:2] == "0x"
}
obscuren's avatar
obscuren committed
94

95 96 97 98 99 100 101 102 103
func Bytes2Hex(d []byte) string {
	return hex.EncodeToString(d)
}

func Hex2Bytes(str string) []byte {
	h, _ := hex.DecodeString(str)
	return h
}

obscuren's avatar
obscuren committed
104
func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
105
	if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
106
		ret = Hex2Bytes(str[2:])
obscuren's avatar
obscuren committed
107 108 109 110 111 112
	} else {
		ret = cb(str)
	}

	return
}
obscuren's avatar
obscuren committed
113 114 115 116 117 118 119 120

func FormatData(data string) []byte {
	if len(data) == 0 {
		return nil
	}
	// Simple stupid
	d := new(big.Int)
	if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
obscuren's avatar
obscuren committed
121
		return RightPadBytes([]byte(data[1:len(data)-1]), 32)
obscuren's avatar
obscuren committed
122
	} else if len(data) > 1 && data[:2] == "0x" {
123
		d.SetBytes(Hex2Bytes(data[2:]))
obscuren's avatar
obscuren committed
124 125 126 127 128 129
	} else {
		d.SetString(data, 0)
	}

	return BigToBytes(d, 256)
}
130

obscuren's avatar
obscuren committed
131
func RightPadBytes(slice []byte, l int) []byte {
obscuren's avatar
obscuren committed
132
	if l < len(slice) {
133 134 135 136 137 138 139 140 141
		return slice
	}

	padded := make([]byte, l)
	copy(padded[0:len(slice)], slice)

	return padded
}

obscuren's avatar
obscuren committed
142
func LeftPadBytes(slice []byte, l int) []byte {
obscuren's avatar
obscuren committed
143
	if l < len(slice) {
144 145 146 147 148 149 150 151
		return slice
	}

	padded := make([]byte, l)
	copy(padded[l-len(slice):], slice)

	return padded
}
152

obscuren's avatar
obscuren committed
153
func Address(slice []byte) (addr []byte) {
154
	if len(slice) < 20 {
obscuren's avatar
obscuren committed
155
		addr = LeftPadBytes(slice, 20)
156
	} else if len(slice) > 20 {
obscuren's avatar
obscuren committed
157 158 159
		addr = slice[len(slice)-20:]
	} else {
		addr = slice
160 161
	}

obscuren's avatar
obscuren committed
162 163 164
	addr = CopyBytes(addr)

	return
165
}