1
2
3
4
5
6 package hex
7
8 import (
9 "errors"
10 "fmt"
11 "io"
12 "strings"
13 )
14
15 const (
16 hextable = "0123456789abcdef"
17 reverseHexTable = "" +
18 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
19 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
20 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
21 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" +
22 "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
23 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
24 "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
25 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
26 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
27 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
28 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
29 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
30 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
31 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
32 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
33 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
34 )
35
36
37
38 func EncodedLen(n int) int { return n * 2 }
39
40
41
42
43
44 func Encode(dst, src []byte) int {
45 j := 0
46 for _, v := range src {
47 dst[j] = hextable[v>>4]
48 dst[j+1] = hextable[v&0x0f]
49 j += 2
50 }
51 return len(src) * 2
52 }
53
54
55
56
57 var ErrLength = errors.New("encoding/hex: odd length hex string")
58
59
60 type InvalidByteError byte
61
62 func (e InvalidByteError) Error() string {
63 return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
64 }
65
66
67
68 func DecodedLen(x int) int { return x / 2 }
69
70
71
72
73
74
75
76
77 func Decode(dst, src []byte) (int, error) {
78 i, j := 0, 1
79 for ; j < len(src); j += 2 {
80 p := src[j-1]
81 q := src[j]
82
83 a := reverseHexTable[p]
84 b := reverseHexTable[q]
85 if a > 0x0f {
86 return i, InvalidByteError(p)
87 }
88 if b > 0x0f {
89 return i, InvalidByteError(q)
90 }
91 dst[i] = (a << 4) | b
92 i++
93 }
94 if len(src)%2 == 1 {
95
96
97 if reverseHexTable[src[j-1]] > 0x0f {
98 return i, InvalidByteError(src[j-1])
99 }
100 return i, ErrLength
101 }
102 return i, nil
103 }
104
105
106 func EncodeToString(src []byte) string {
107 dst := make([]byte, EncodedLen(len(src)))
108 Encode(dst, src)
109 return string(dst)
110 }
111
112
113
114
115
116
117
118 func DecodeString(s string) ([]byte, error) {
119 src := []byte(s)
120
121
122 n, err := Decode(src, src)
123 return src[:n], err
124 }
125
126
127
128 func Dump(data []byte) string {
129 if len(data) == 0 {
130 return ""
131 }
132
133 var buf strings.Builder
134
135
136
137 buf.Grow((1 + ((len(data) - 1) / 16)) * 79)
138
139 dumper := Dumper(&buf)
140 dumper.Write(data)
141 dumper.Close()
142 return buf.String()
143 }
144
145
146 const bufferSize = 1024
147
148 type encoder struct {
149 w io.Writer
150 err error
151 out [bufferSize]byte
152 }
153
154
155 func NewEncoder(w io.Writer) io.Writer {
156 return &encoder{w: w}
157 }
158
159 func (e *encoder) Write(p []byte) (n int, err error) {
160 for len(p) > 0 && e.err == nil {
161 chunkSize := bufferSize / 2
162 if len(p) < chunkSize {
163 chunkSize = len(p)
164 }
165
166 var written int
167 encoded := Encode(e.out[:], p[:chunkSize])
168 written, e.err = e.w.Write(e.out[:encoded])
169 n += written / 2
170 p = p[chunkSize:]
171 }
172 return n, e.err
173 }
174
175 type decoder struct {
176 r io.Reader
177 err error
178 in []byte
179 arr [bufferSize]byte
180 }
181
182
183
184 func NewDecoder(r io.Reader) io.Reader {
185 return &decoder{r: r}
186 }
187
188 func (d *decoder) Read(p []byte) (n int, err error) {
189
190 if len(d.in) < 2 && d.err == nil {
191 var numCopy, numRead int
192 numCopy = copy(d.arr[:], d.in)
193 numRead, d.err = d.r.Read(d.arr[numCopy:])
194 d.in = d.arr[:numCopy+numRead]
195 if d.err == io.EOF && len(d.in)%2 != 0 {
196
197 if a := reverseHexTable[d.in[len(d.in)-1]]; a > 0x0f {
198 d.err = InvalidByteError(d.in[len(d.in)-1])
199 } else {
200 d.err = io.ErrUnexpectedEOF
201 }
202 }
203 }
204
205
206 if numAvail := len(d.in) / 2; len(p) > numAvail {
207 p = p[:numAvail]
208 }
209 numDec, err := Decode(p, d.in[:len(p)*2])
210 d.in = d.in[2*numDec:]
211 if err != nil {
212 d.in, d.err = nil, err
213 }
214
215 if len(d.in) < 2 {
216 return numDec, d.err
217 }
218 return numDec, nil
219 }
220
221
222
223
224 func Dumper(w io.Writer) io.WriteCloser {
225 return &dumper{w: w}
226 }
227
228 type dumper struct {
229 w io.Writer
230 rightChars [18]byte
231 buf [14]byte
232 used int
233 n uint
234 closed bool
235 }
236
237 func toChar(b byte) byte {
238 if b < 32 || b > 126 {
239 return '.'
240 }
241 return b
242 }
243
244 func (h *dumper) Write(data []byte) (n int, err error) {
245 if h.closed {
246 return 0, errors.New("encoding/hex: dumper closed")
247 }
248
249
250
251
252 for i := range data {
253 if h.used == 0 {
254
255
256 h.buf[0] = byte(h.n >> 24)
257 h.buf[1] = byte(h.n >> 16)
258 h.buf[2] = byte(h.n >> 8)
259 h.buf[3] = byte(h.n)
260 Encode(h.buf[4:], h.buf[:4])
261 h.buf[12] = ' '
262 h.buf[13] = ' '
263 _, err = h.w.Write(h.buf[4:])
264 if err != nil {
265 return
266 }
267 }
268 Encode(h.buf[:], data[i:i+1])
269 h.buf[2] = ' '
270 l := 3
271 if h.used == 7 {
272
273 h.buf[3] = ' '
274 l = 4
275 } else if h.used == 15 {
276
277
278 h.buf[3] = ' '
279 h.buf[4] = '|'
280 l = 5
281 }
282 _, err = h.w.Write(h.buf[:l])
283 if err != nil {
284 return
285 }
286 n++
287 h.rightChars[h.used] = toChar(data[i])
288 h.used++
289 h.n++
290 if h.used == 16 {
291 h.rightChars[16] = '|'
292 h.rightChars[17] = '\n'
293 _, err = h.w.Write(h.rightChars[:])
294 if err != nil {
295 return
296 }
297 h.used = 0
298 }
299 }
300 return
301 }
302
303 func (h *dumper) Close() (err error) {
304
305 if h.closed {
306 return
307 }
308 h.closed = true
309 if h.used == 0 {
310 return
311 }
312 h.buf[0] = ' '
313 h.buf[1] = ' '
314 h.buf[2] = ' '
315 h.buf[3] = ' '
316 h.buf[4] = '|'
317 nBytes := h.used
318 for h.used < 16 {
319 l := 3
320 if h.used == 7 {
321 l = 4
322 } else if h.used == 15 {
323 l = 5
324 }
325 _, err = h.w.Write(h.buf[:l])
326 if err != nil {
327 return
328 }
329 h.used++
330 }
331 h.rightChars[nBytes] = '|'
332 h.rightChars[nBytes+1] = '\n'
333 _, err = h.w.Write(h.rightChars[:nBytes+2])
334 return
335 }
336
View as plain text