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