OSDN Git Service

Clean vendor (#1309)
[bytom/bytom.git] / common / bytes.go
1 // Package common contains various helper functions.
2 package common
3
4 import (
5         "bytes"
6         "encoding/binary"
7         "encoding/hex"
8         "math/big"
9         "strings"
10
11         log "github.com/sirupsen/logrus"
12 )
13
14 func ToHex(b []byte) string {
15         hex := Bytes2Hex(b)
16         // Prefer output of "0x0" instead of "0x"
17         if len(hex) == 0 {
18                 hex = "0"
19         }
20         return "0x" + hex
21 }
22
23 func FromHex(s string) []byte {
24         if len(s) > 1 {
25                 if s[0:2] == "0x" {
26                         s = s[2:]
27                 }
28                 if len(s)%2 == 1 {
29                         s = "0" + s
30                 }
31                 return Hex2Bytes(s)
32         }
33         return nil
34 }
35
36 // Number to bytes
37 //
38 // Returns the number in bytes with the specified base
39 func NumberToBytes(num interface{}, bits int) []byte {
40         buf := new(bytes.Buffer)
41         err := binary.Write(buf, binary.BigEndian, num)
42         if err != nil {
43                 log.WithField("err", err).Error("NumberToBytes failed")
44         }
45
46         return buf.Bytes()[buf.Len()-(bits/8):]
47 }
48
49 // Bytes to number
50 //
51 // Attempts to cast a byte slice to a unsigned integer
52 func BytesToNumber(b []byte) uint64 {
53         var number uint64
54
55         // Make sure the buffer is 64bits
56         data := make([]byte, 8)
57         data = append(data[:len(b)], b...)
58
59         buf := bytes.NewReader(data)
60         err := binary.Read(buf, binary.BigEndian, &number)
61         if err != nil {
62                 log.WithField("err", err).Error("BytesToNumber failed")
63         }
64
65         return number
66 }
67
68 // Read variable int
69 //
70 // Read a variable length number in big endian byte order
71 func ReadVarInt(buff []byte) (ret uint64) {
72         switch l := len(buff); {
73         case l > 4:
74                 d := LeftPadBytes(buff, 8)
75                 binary.Read(bytes.NewReader(d), binary.BigEndian, &ret)
76         case l > 2:
77                 var num uint32
78                 d := LeftPadBytes(buff, 4)
79                 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
80                 ret = uint64(num)
81         case l > 1:
82                 var num uint16
83                 d := LeftPadBytes(buff, 2)
84                 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
85                 ret = uint64(num)
86         default:
87                 var num uint8
88                 binary.Read(bytes.NewReader(buff), binary.BigEndian, &num)
89                 ret = uint64(num)
90         }
91
92         return
93 }
94
95 // Copy bytes
96 //
97 // Returns an exact copy of the provided bytes
98 func CopyBytes(b []byte) (copiedBytes []byte) {
99         copiedBytes = make([]byte, len(b))
100         copy(copiedBytes, b)
101
102         return
103 }
104
105 func HasHexPrefix(str string) bool {
106         l := len(str)
107         return l >= 2 && str[0:2] == "0x"
108 }
109
110 func IsHex(str string) bool {
111         l := len(str)
112         return l >= 4 && l%2 == 0 && str[0:2] == "0x"
113 }
114
115 func Bytes2Hex(d []byte) string {
116         return hex.EncodeToString(d)
117 }
118
119 func Hex2Bytes(str string) []byte {
120         h, _ := hex.DecodeString(str)
121
122         return h
123 }
124
125 func Hex2BytesFixed(str string, flen int) []byte {
126         h, _ := hex.DecodeString(str)
127         if len(h) == flen {
128                 return h
129         } else {
130                 if len(h) > flen {
131                         return h[len(h)-flen : len(h)]
132                 } else {
133                         hh := make([]byte, flen)
134                         copy(hh[flen-len(h):flen], h[:])
135                         return hh
136                 }
137         }
138 }
139
140 func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
141         if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
142                 ret = Hex2Bytes(str[2:])
143         } else {
144                 ret = cb(str)
145         }
146
147         return
148 }
149
150 func FormatData(data string) []byte {
151         if len(data) == 0 {
152                 return nil
153         }
154         // Simple stupid
155         d := new(big.Int)
156         if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
157                 return RightPadBytes([]byte(data[1:len(data)-1]), 32)
158         } else if len(data) > 1 && data[:2] == "0x" {
159                 d.SetBytes(Hex2Bytes(data[2:]))
160         } else {
161                 d.SetString(data, 0)
162         }
163
164         return BigToBytes(d, 256)
165 }
166
167 func ParseData(data ...interface{}) (ret []byte) {
168         for _, item := range data {
169                 switch t := item.(type) {
170                 case string:
171                         var str []byte
172                         if IsHex(t) {
173                                 str = Hex2Bytes(t[2:])
174                         } else {
175                                 str = []byte(t)
176                         }
177
178                         ret = append(ret, RightPadBytes(str, 32)...)
179                 case []byte:
180                         ret = append(ret, LeftPadBytes(t, 32)...)
181                 }
182         }
183
184         return
185 }
186
187 func RightPadBytes(slice []byte, l int) []byte {
188         if l < len(slice) {
189                 return slice
190         }
191
192         padded := make([]byte, l)
193         copy(padded[0:len(slice)], slice)
194
195         return padded
196 }
197
198 func LeftPadBytes(slice []byte, l int) []byte {
199         if l < len(slice) {
200                 return slice
201         }
202
203         padded := make([]byte, l)
204         copy(padded[l-len(slice):], slice)
205
206         return padded
207 }
208
209 func LeftPadString(str string, l int) string {
210         if l < len(str) {
211                 return str
212         }
213
214         zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
215
216         return zeros + str
217
218 }
219
220 func RightPadString(str string, l int) string {
221         if l < len(str) {
222                 return str
223         }
224
225         zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
226
227         return str + zeros
228
229 }
230
231 func ToAddress(slice []byte) (addr []byte) {
232         if len(slice) < 20 {
233                 addr = LeftPadBytes(slice, 20)
234         } else if len(slice) > 20 {
235                 addr = slice[len(slice)-20:]
236         } else {
237                 addr = slice
238         }
239
240         addr = CopyBytes(addr)
241
242         return
243 }
244
245 func ByteSliceToInterface(slice [][]byte) (ret []interface{}) {
246         for _, i := range slice {
247                 ret = append(ret, i)
248         }
249
250         return
251 }
252
253 func Unit64ToBytes(n uint64) []byte {
254         buf := make([]byte, 8)
255         binary.LittleEndian.PutUint64(buf, n)
256         return buf
257 }
258
259 func BytesToUnit64(b []byte) uint64 {
260         return binary.LittleEndian.Uint64(b)
261 }