1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package hex implements hexadecimal encoding and decoding.
6package hex
7
8import (
9	"errors"
10	"fmt"
11	"io"
12	"strings"
13)
14
15const hextable = "0123456789abcdef"
16
17// EncodedLen returns the length of an encoding of n source bytes.
18// Specifically, it returns n * 2.
19func EncodedLen(n int) int { return n * 2 }
20
21// Encode encodes src into EncodedLen(len(src))
22// bytes of dst. As a convenience, it returns the number
23// of bytes written to dst, but this value is always EncodedLen(len(src)).
24// Encode implements hexadecimal encoding.
25func Encode(dst, src []byte) int {
26	j := 0
27	for _, v := range src {
28		dst[j] = hextable[v>>4]
29		dst[j+1] = hextable[v&0x0f]
30		j += 2
31	}
32	return len(src) * 2
33}
34
35// ErrLength reports an attempt to decode an odd-length input
36// using Decode or DecodeString.
37// The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength.
38var ErrLength = errors.New("encoding/hex: odd length hex string")
39
40// InvalidByteError values describe errors resulting from an invalid byte in a hex string.
41type InvalidByteError byte
42
43func (e InvalidByteError) Error() string {
44	return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
45}
46
47// DecodedLen returns the length of a decoding of x source bytes.
48// Specifically, it returns x / 2.
49func DecodedLen(x int) int { return x / 2 }
50
51// Decode decodes src into DecodedLen(len(src)) bytes,
52// returning the actual number of bytes written to dst.
53//
54// Decode expects that src contains only hexadecimal
55// characters and that src has even length.
56// If the input is malformed, Decode returns the number
57// of bytes decoded before the error.
58func Decode(dst, src []byte) (int, error) {
59	i, j := 0, 1
60	for ; j < len(src); j += 2 {
61		a, ok := fromHexChar(src[j-1])
62		if !ok {
63			return i, InvalidByteError(src[j-1])
64		}
65		b, ok := fromHexChar(src[j])
66		if !ok {
67			return i, InvalidByteError(src[j])
68		}
69		dst[i] = (a << 4) | b
70		i++
71	}
72	if len(src)%2 == 1 {
73		// Check for invalid char before reporting bad length,
74		// since the invalid char (if present) is an earlier problem.
75		if _, ok := fromHexChar(src[j-1]); !ok {
76			return i, InvalidByteError(src[j-1])
77		}
78		return i, ErrLength
79	}
80	return i, nil
81}
82
83// fromHexChar converts a hex character into its value and a success flag.
84func fromHexChar(c byte) (byte, bool) {
85	switch {
86	case '0' <= c && c <= '9':
87		return c - '0', true
88	case 'a' <= c && c <= 'f':
89		return c - 'a' + 10, true
90	case 'A' <= c && c <= 'F':
91		return c - 'A' + 10, true
92	}
93
94	return 0, false
95}
96
97// EncodeToString returns the hexadecimal encoding of src.
98func EncodeToString(src []byte) string {
99	dst := make([]byte, EncodedLen(len(src)))
100	Encode(dst, src)
101	return string(dst)
102}
103
104// DecodeString returns the bytes represented by the hexadecimal string s.
105//
106// DecodeString expects that src contains only hexadecimal
107// characters and that src has even length.
108// If the input is malformed, DecodeString returns
109// the bytes decoded before the error.
110func DecodeString(s string) ([]byte, error) {
111	src := []byte(s)
112	// We can use the source slice itself as the destination
113	// because the decode loop increments by one and then the 'seen' byte is not used anymore.
114	n, err := Decode(src, src)
115	return src[:n], err
116}
117
118// Dump returns a string that contains a hex dump of the given data. The format
119// of the hex dump matches the output of `hexdump -C` on the command line.
120func Dump(data []byte) string {
121	if len(data) == 0 {
122		return ""
123	}
124
125	var buf strings.Builder
126	// Dumper will write 79 bytes per complete 16 byte chunk, and at least
127	// 64 bytes for whatever remains. Round the allocation up, since only a
128	// maximum of 15 bytes will be wasted.
129	buf.Grow((1 + ((len(data) - 1) / 16)) * 79)
130
131	dumper := Dumper(&buf)
132	dumper.Write(data)
133	dumper.Close()
134	return buf.String()
135}
136
137// bufferSize is the number of hexadecimal characters to buffer in encoder and decoder.
138const bufferSize = 1024
139
140type encoder struct {
141	w   io.Writer
142	err error
143	out [bufferSize]byte // output buffer
144}
145
146// NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w.
147func NewEncoder(w io.Writer) io.Writer {
148	return &encoder{w: w}
149}
150
151func (e *encoder) Write(p []byte) (n int, err error) {
152	for len(p) > 0 && e.err == nil {
153		chunkSize := bufferSize / 2
154		if len(p) < chunkSize {
155			chunkSize = len(p)
156		}
157
158		var written int
159		encoded := Encode(e.out[:], p[:chunkSize])
160		written, e.err = e.w.Write(e.out[:encoded])
161		n += written / 2
162		p = p[chunkSize:]
163	}
164	return n, e.err
165}
166
167type decoder struct {
168	r   io.Reader
169	err error
170	in  []byte           // input buffer (encoded form)
171	arr [bufferSize]byte // backing array for in
172}
173
174// NewDecoder returns an io.Reader that decodes hexadecimal characters from r.
175// NewDecoder expects that r contain only an even number of hexadecimal characters.
176func NewDecoder(r io.Reader) io.Reader {
177	return &decoder{r: r}
178}
179
180func (d *decoder) Read(p []byte) (n int, err error) {
181	// Fill internal buffer with sufficient bytes to decode
182	if len(d.in) < 2 && d.err == nil {
183		var numCopy, numRead int
184		numCopy = copy(d.arr[:], d.in) // Copies either 0 or 1 bytes
185		numRead, d.err = d.r.Read(d.arr[numCopy:])
186		d.in = d.arr[:numCopy+numRead]
187		if d.err == io.EOF && len(d.in)%2 != 0 {
188			if _, ok := fromHexChar(d.in[len(d.in)-1]); !ok {
189				d.err = InvalidByteError(d.in[len(d.in)-1])
190			} else {
191				d.err = io.ErrUnexpectedEOF
192			}
193		}
194	}
195
196	// Decode internal buffer into output buffer
197	if numAvail := len(d.in) / 2; len(p) > numAvail {
198		p = p[:numAvail]
199	}
200	numDec, err := Decode(p, d.in[:len(p)*2])
201	d.in = d.in[2*numDec:]
202	if err != nil {
203		d.in, d.err = nil, err // Decode error; discard input remainder
204	}
205
206	if len(d.in) < 2 {
207		return numDec, d.err // Only expose errors when buffer fully consumed
208	}
209	return numDec, nil
210}
211
212// Dumper returns a WriteCloser that writes a hex dump of all written data to
213// w. The format of the dump matches the output of `hexdump -C` on the command
214// line.
215func Dumper(w io.Writer) io.WriteCloser {
216	return &dumper{w: w}
217}
218
219type dumper struct {
220	w          io.Writer
221	rightChars [18]byte
222	buf        [14]byte
223	used       int  // number of bytes in the current line
224	n          uint // number of bytes, total
225	closed     bool
226}
227
228func toChar(b byte) byte {
229	if b < 32 || b > 126 {
230		return '.'
231	}
232	return b
233}
234
235func (h *dumper) Write(data []byte) (n int, err error) {
236	if h.closed {
237		return 0, errors.New("encoding/hex: dumper closed")
238	}
239
240	// Output lines look like:
241	// 00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
242	// ^ offset                          ^ extra space              ^ ASCII of line.
243	for i := range data {
244		if h.used == 0 {
245			// At the beginning of a line we print the current
246			// offset in hex.
247			h.buf[0] = byte(h.n >> 24)
248			h.buf[1] = byte(h.n >> 16)
249			h.buf[2] = byte(h.n >> 8)
250			h.buf[3] = byte(h.n)
251			Encode(h.buf[4:], h.buf[:4])
252			h.buf[12] = ' '
253			h.buf[13] = ' '
254			_, err = h.w.Write(h.buf[4:])
255			if err != nil {
256				return
257			}
258		}
259		Encode(h.buf[:], data[i:i+1])
260		h.buf[2] = ' '
261		l := 3
262		if h.used == 7 {
263			// There's an additional space after the 8th byte.
264			h.buf[3] = ' '
265			l = 4
266		} else if h.used == 15 {
267			// At the end of the line there's an extra space and
268			// the bar for the right column.
269			h.buf[3] = ' '
270			h.buf[4] = '|'
271			l = 5
272		}
273		_, err = h.w.Write(h.buf[:l])
274		if err != nil {
275			return
276		}
277		n++
278		h.rightChars[h.used] = toChar(data[i])
279		h.used++
280		h.n++
281		if h.used == 16 {
282			h.rightChars[16] = '|'
283			h.rightChars[17] = '\n'
284			_, err = h.w.Write(h.rightChars[:])
285			if err != nil {
286				return
287			}
288			h.used = 0
289		}
290	}
291	return
292}
293
294func (h *dumper) Close() (err error) {
295	// See the comments in Write() for the details of this format.
296	if h.closed {
297		return
298	}
299	h.closed = true
300	if h.used == 0 {
301		return
302	}
303	h.buf[0] = ' '
304	h.buf[1] = ' '
305	h.buf[2] = ' '
306	h.buf[3] = ' '
307	h.buf[4] = '|'
308	nBytes := h.used
309	for h.used < 16 {
310		l := 3
311		if h.used == 7 {
312			l = 4
313		} else if h.used == 15 {
314			l = 5
315		}
316		_, err = h.w.Write(h.buf[:l])
317		if err != nil {
318			return
319		}
320		h.used++
321	}
322	h.rightChars[nBytes] = '|'
323	h.rightChars[nBytes+1] = '\n'
324	_, err = h.w.Write(h.rightChars[:nBytes+2])
325	return
326}
327