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.
5 // Package hex implements hexadecimal encoding and decoding.
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"
37 // EncodedLen returns the length of an encoding of n source bytes.
38 // Specifically, it returns n * 2.
39 func EncodedLen(n int) int { return n * 2 }
41 // Encode encodes src into EncodedLen(len(src))
42 // bytes of dst. As a convenience, it returns the number
43 // of bytes written to dst, but this value is always EncodedLen(len(src)).
44 // Encode implements hexadecimal encoding.
45 func Encode(dst, src []byte) int {
47 for _, v := range src {
48 dst[j] = hextable[v>>4]
49 dst[j+1] = hextable[v&0x0f]
55 // AppendEncode appends the hexadecimally encoded src to dst
56 // and returns the extended buffer.
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]
64 // ErrLength reports an attempt to decode an odd-length input
65 // using Decode or DecodeString.
66 // The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength.
67 var ErrLength = errors.New("encoding/hex: odd length hex string")
69 // InvalidByteError values describe errors resulting from an invalid byte in a hex string.
70 type InvalidByteError byte
72 func (e InvalidByteError) Error() string {
73 return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
76 // DecodedLen returns the length of a decoding of x source bytes.
77 // Specifically, it returns x / 2.
78 func DecodedLen(x int) int { return x / 2 }
80 // Decode decodes src into DecodedLen(len(src)) bytes,
81 // returning the actual number of bytes written to dst.
83 // Decode expects that src contains only hexadecimal
84 // characters and that src has even length.
85 // If the input is malformed, Decode returns the number
86 // of bytes decoded before the error.
87 func Decode(dst, src []byte) (int, error) {
89 for ; j < len(src); j += 2 {
93 a := reverseHexTable[p]
94 b := reverseHexTable[q]
96 return i, InvalidByteError(p)
99 return i, InvalidByteError(q)
101 dst[i] = (a << 4) | b
105 // Check for invalid char before reporting bad length,
106 // since the invalid char (if present) is an earlier problem.
107 if reverseHexTable[src[j-1]] > 0x0f {
108 return i, InvalidByteError(src[j-1])
115 // AppendDecode appends the hexadecimally decoded src to dst
116 // and returns the extended buffer.
117 // If the input is malformed, it returns the partially decoded src and an error.
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
125 // EncodeToString returns the hexadecimal encoding of src.
126 func EncodeToString(src []byte) string {
127 dst := make([]byte, EncodedLen(len(src)))
132 // DecodeString returns the bytes represented by the hexadecimal string s.
134 // DecodeString expects that src contains only hexadecimal
135 // characters and that src has even length.
136 // If the input is malformed, DecodeString returns
137 // the bytes decoded before the error.
138 func DecodeString(s string) ([]byte, error) {
140 // We can use the source slice itself as the destination
141 // because the decode loop increments by one and then the 'seen' byte is not used anymore.
142 n, err := Decode(src, src)
146 // Dump returns a string that contains a hex dump of the given data. The format
147 // of the hex dump matches the output of `hexdump -C` on the command line.
148 func Dump(data []byte) string {
153 var buf strings.Builder
154 // Dumper will write 79 bytes per complete 16 byte chunk, and at least
155 // 64 bytes for whatever remains. Round the allocation up, since only a
156 // maximum of 15 bytes will be wasted.
157 buf.Grow((1 + ((len(data) - 1) / 16)) * 79)
159 dumper := Dumper(&buf)
165 // bufferSize is the number of hexadecimal characters to buffer in encoder and decoder.
166 const bufferSize = 1024
168 type encoder struct {
171 out [bufferSize]byte // output buffer
174 // NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w.
175 func NewEncoder(w io.Writer) io.Writer {
176 return &encoder{w: w}
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 {
187 encoded := Encode(e.out[:], p[:chunkSize])
188 written, e.err = e.w.Write(e.out[:encoded])
195 type decoder struct {
198 in []byte // input buffer (encoded form)
199 arr [bufferSize]byte // backing array for in
202 // NewDecoder returns an io.Reader that decodes hexadecimal characters from r.
203 // NewDecoder expects that r contain only an even number of hexadecimal characters.
204 func NewDecoder(r io.Reader) io.Reader {
205 return &decoder{r: r}
208 func (d *decoder) Read(p []byte) (n int, err error) {
209 // Fill internal buffer with sufficient bytes to decode
210 if len(d.in) < 2 && d.err == nil {
211 var numCopy, numRead int
212 numCopy = copy(d.arr[:], d.in) // Copies either 0 or 1 bytes
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 {
217 if a := reverseHexTable[d.in[len(d.in)-1]]; a > 0x0f {
218 d.err = InvalidByteError(d.in[len(d.in)-1])
220 d.err = io.ErrUnexpectedEOF
225 // Decode internal buffer into output buffer
226 if numAvail := len(d.in) / 2; len(p) > numAvail {
229 numDec, err := Decode(p, d.in[:len(p)*2])
230 d.in = d.in[2*numDec:]
232 d.in, d.err = nil, err // Decode error; discard input remainder
236 return numDec, d.err // Only expose errors when buffer fully consumed
241 // Dumper returns a WriteCloser that writes a hex dump of all written data to
242 // w. The format of the dump matches the output of `hexdump -C` on the command
244 func Dumper(w io.Writer) io.WriteCloser {
252 used int // number of bytes in the current line
253 n uint // number of bytes, total
257 func toChar(b byte) byte {
258 if b < 32 || b > 126 {
264 func (h *dumper) Write(data []byte) (n int, err error) {
266 return 0, errors.New("encoding/hex: dumper closed")
269 // Output lines look like:
270 // 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=|
271 // ^ offset ^ extra space ^ ASCII of line.
272 for i := range data {
274 // At the beginning of a line we print the current
276 h.buf[0] = byte(h.n >> 24)
277 h.buf[1] = byte(h.n >> 16)
278 h.buf[2] = byte(h.n >> 8)
280 Encode(h.buf[4:], h.buf[:4])
283 _, err = h.w.Write(h.buf[4:])
288 Encode(h.buf[:], data[i:i+1])
292 // There's an additional space after the 8th byte.
295 } else if h.used == 15 {
296 // At the end of the line there's an extra space and
297 // the bar for the right column.
302 _, err = h.w.Write(h.buf[:l])
307 h.rightChars[h.used] = toChar(data[i])
311 h.rightChars[16] = '|'
312 h.rightChars[17] = '\n'
313 _, err = h.w.Write(h.rightChars[:])
323 func (h *dumper) Close() (err error) {
324 // See the comments in Write() for the details of this format.
342 } else if h.used == 15 {
345 _, err = h.w.Write(h.buf[:l])
351 h.rightChars[nBytes] = '|'
352 h.rightChars[nBytes+1] = '\n'
353 _, err = h.w.Write(h.rightChars[:nBytes+2])