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	"bytes"
10	"errors"
11	"fmt"
12	"io"
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	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// ErrLength reports an attempt to decode an odd-length input
35// using Decode or DecodeString.
36// The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength.
37var ErrLength = errors.New("encoding/hex: odd length hex string")
38
39// InvalidByteError values describe errors resulting from an invalid byte in a hex string.
40type InvalidByteError byte
41
42func (e InvalidByteError) Error() string {
43	return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
44}
45
46// DecodedLen returns the length of a decoding of x source bytes.
47// Specifically, it returns x / 2.
48func DecodedLen(x int) int { return x / 2 }
49
50// Decode decodes src into DecodedLen(len(src)) bytes,
51// returning the actual number of bytes written to dst.
52//
53// Decode expects that src contain only hexadecimal
54// characters and that src should have an even length.
55// If the input is malformed, Decode returns the number
56// of bytes decoded before the error.
57func 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		// Check for invalid char before reporting bad length,
72		// since the invalid char (if present) is an earlier problem.
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// fromHexChar converts a hex character into its value and a success flag.
82func 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// EncodeToString returns the hexadecimal encoding of src.
96func EncodeToString(src []byte) string {
97	dst := make([]byte, EncodedLen(len(src)))
98	Encode(dst, src)
99	return string(dst)
100}
101
102// DecodeString returns the bytes represented by the hexadecimal string s.
103//
104// DecodeString expects that src contain only hexadecimal
105// characters and that src should have an even length.
106// If the input is malformed, DecodeString returns a string
107// containing the bytes decoded before the error.
108func DecodeString(s string) ([]byte, error) {
109	src := []byte(s)
110	// We can use the source slice itself as the destination
111	// because the decode loop increments by one and then the 'seen' byte is not used anymore.
112	n, err := Decode(src, src)
113	return src[:n], err
114}
115
116// Dump returns a string that contains a hex dump of the given data. The format
117// of the hex dump matches the output of `hexdump -C` on the command line.
118func 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// bufferSize is the number of hexadecimal characters to buffer in encoder and decoder.
127const bufferSize = 1024
128
129type encoder struct {
130	w   io.Writer
131	err error
132	out [bufferSize]byte // output buffer
133}
134
135// NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w.
136func NewEncoder(w io.Writer) io.Writer {
137	return &encoder{w: w}
138}
139
140func (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
156type decoder struct {
157	r   io.Reader
158	err error
159	in  []byte           // input buffer (encoded form)
160	arr [bufferSize]byte // backing array for in
161}
162
163// NewDecoder returns an io.Reader that decodes hexadecimal characters from r.
164// NewDecoder expects that r contain only an even number of hexadecimal characters.
165func NewDecoder(r io.Reader) io.Reader {
166	return &decoder{r: r}
167}
168
169func (d *decoder) Read(p []byte) (n int, err error) {
170	// Fill internal buffer with sufficient bytes to decode
171	if len(d.in) < 2 && d.err == nil {
172		var numCopy, numRead int
173		numCopy = copy(d.arr[:], d.in) // Copies either 0 or 1 bytes
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	// Decode internal buffer into output buffer
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 // Decode error; discard input remainder
193	}
194
195	if len(d.in) < 2 {
196		return numDec, d.err // Only expose errors when buffer fully consumed
197	}
198	return numDec, nil
199}
200
201// Dumper returns a WriteCloser that writes a hex dump of all written data to
202// w. The format of the dump matches the output of `hexdump -C` on the command
203// line.
204func Dumper(w io.Writer) io.WriteCloser {
205	return &dumper{w: w}
206}
207
208type dumper struct {
209	w          io.Writer
210	rightChars [18]byte
211	buf        [14]byte
212	used       int  // number of bytes in the current line
213	n          uint // number of bytes, total
214}
215
216func toChar(b byte) byte {
217	if b < 32 || b > 126 {
218		return '.'
219	}
220	return b
221}
222
223func (h *dumper) Write(data []byte) (n int, err error) {
224	// Output lines look like:
225	// 00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
226	// ^ offset                          ^ extra space              ^ ASCII of line.
227	for i := range data {
228		if h.used == 0 {
229			// At the beginning of a line we print the current
230			// offset in hex.
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			// There's an additional space after the 8th byte.
248			h.buf[3] = ' '
249			l = 4
250		} else if h.used == 15 {
251			// At the end of the line there's an extra space and
252			// the bar for the right column.
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
278func (h *dumper) Close() (err error) {
279	// See the comments in Write() for the details of this format.
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