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