Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Package hex implements hexadecimal encoding and decoding.
package hex

import (
	
	
	
	
)

const hextable = "0123456789abcdef"
EncodedLen returns the length of an encoding of n source bytes. Specifically, it returns n * 2.
func ( int) int { return  * 2 }
Encode encodes src into EncodedLen(len(src)) bytes of dst. As a convenience, it returns the number of bytes written to dst, but this value is always EncodedLen(len(src)). Encode implements hexadecimal encoding.
func (,  []byte) int {
	 := 0
	for ,  := range  {
		[] = hextable[>>4]
		[+1] = hextable[&0x0f]
		 += 2
	}
	return len() * 2
}
ErrLength reports an attempt to decode an odd-length input using Decode or DecodeString. The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength.
var ErrLength = errors.New("encoding/hex: odd length hex string")
InvalidByteError values describe errors resulting from an invalid byte in a hex string.
type InvalidByteError byte

func ( InvalidByteError) () string {
	return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune())
}
DecodedLen returns the length of a decoding of x source bytes. Specifically, it returns x / 2.
func ( int) int { return  / 2 }
Decode decodes src into DecodedLen(len(src)) bytes, returning the actual number of bytes written to dst. Decode expects that src contains only hexadecimal characters and that src has even length. If the input is malformed, Decode returns the number of bytes decoded before the error.
func (,  []byte) (int, error) {
	,  := 0, 1
	for ;  < len();  += 2 {
		,  := fromHexChar([-1])
		if ! {
			return , InvalidByteError([-1])
		}
		,  := fromHexChar([])
		if ! {
			return , InvalidByteError([])
		}
		[] = ( << 4) | 
		++
	}
Check for invalid char before reporting bad length, since the invalid char (if present) is an earlier problem.
		if ,  := fromHexChar([-1]); ! {
			return , InvalidByteError([-1])
		}
		return , ErrLength
	}
	return , nil
}
fromHexChar converts a hex character into its value and a success flag.
func ( byte) (byte, bool) {
	switch {
	case '0' <=  &&  <= '9':
		return  - '0', true
	case 'a' <=  &&  <= 'f':
		return  - 'a' + 10, true
	case 'A' <=  &&  <= 'F':
		return  - 'A' + 10, true
	}

	return 0, false
}
EncodeToString returns the hexadecimal encoding of src.
func ( []byte) string {
	 := make([]byte, EncodedLen(len()))
	Encode(, )
	return string()
}
DecodeString returns the bytes represented by the hexadecimal string s. DecodeString expects that src contains only hexadecimal characters and that src has even length. If the input is malformed, DecodeString returns the bytes decoded before the error.
func ( string) ([]byte, error) {
We can use the source slice itself as the destination because the decode loop increments by one and then the 'seen' byte is not used anymore.
	,  := Decode(, )
	return [:], 
}
Dump returns a string that contains a hex dump of the given data. The format of the hex dump matches the output of `hexdump -C` on the command line.
func ( []byte) string {
	if len() == 0 {
		return ""
	}

Dumper will write 79 bytes per complete 16 byte chunk, and at least 64 bytes for whatever remains. Round the allocation up, since only a maximum of 15 bytes will be wasted.
	.Grow((1 + ((len() - 1) / 16)) * 79)

	 := Dumper(&)
	.Write()
	.Close()
	return .String()
}
bufferSize is the number of hexadecimal characters to buffer in encoder and decoder.
const bufferSize = 1024

type encoder struct {
	w   io.Writer
	err error
	out [bufferSize]byte // output buffer
}
NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w.
func ( io.Writer) io.Writer {
	return &encoder{w: }
}

func ( *encoder) ( []byte) ( int,  error) {
	for len() > 0 && .err == nil {
		 := bufferSize / 2
		if len() <  {
			 = len()
		}

		var  int
		 := Encode(.out[:], [:])
		, .err = .w.Write(.out[:])
		 +=  / 2
		 = [:]
	}
	return , .err
}

type decoder struct {
	r   io.Reader
	err error
	in  []byte           // input buffer (encoded form)
	arr [bufferSize]byte // backing array for in
}
NewDecoder returns an io.Reader that decodes hexadecimal characters from r. NewDecoder expects that r contain only an even number of hexadecimal characters.
func ( io.Reader) io.Reader {
	return &decoder{r: }
}

Fill internal buffer with sufficient bytes to decode
	if len(.in) < 2 && .err == nil {
		var ,  int
		 = copy(.arr[:], .in) // Copies either 0 or 1 bytes
		, .err = .r.Read(.arr[:])
		.in = .arr[:+]
		if .err == io.EOF && len(.in)%2 != 0 {
			if ,  := fromHexChar(.in[len(.in)-1]); ! {
				.err = InvalidByteError(.in[len(.in)-1])
			} else {
				.err = io.ErrUnexpectedEOF
			}
		}
	}
Decode internal buffer into output buffer
	if  := len(.in) / 2; len() >  {
		 = [:]
	}
	,  := Decode(, .in[:len()*2])
	.in = .in[2*:]
	if  != nil {
		.in, .err = nil,  // Decode error; discard input remainder
	}

	if len(.in) < 2 {
		return , .err // Only expose errors when buffer fully consumed
	}
	return , nil
}
Dumper returns a WriteCloser that writes a hex dump of all written data to w. The format of the dump matches the output of `hexdump -C` on the command line.
func ( io.Writer) io.WriteCloser {
	return &dumper{w: }
}

type dumper struct {
	w          io.Writer
	rightChars [18]byte
	buf        [14]byte
	used       int  // number of bytes in the current line
	n          uint // number of bytes, total
	closed     bool
}

func ( byte) byte {
	if  < 32 ||  > 126 {
		return '.'
	}
	return 
}

func ( *dumper) ( []byte) ( int,  error) {
	if .closed {
		return 0, errors.New("encoding/hex: dumper closed")
	}
Output lines look like: 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=| ^ offset ^ extra space ^ ASCII of line.
	for  := range  {
At the beginning of a line we print the current offset in hex.
			.buf[0] = byte(.n >> 24)
			.buf[1] = byte(.n >> 16)
			.buf[2] = byte(.n >> 8)
			.buf[3] = byte(.n)
			Encode(.buf[4:], .buf[:4])
			.buf[12] = ' '
			.buf[13] = ' '
			_,  = .w.Write(.buf[4:])
			if  != nil {
				return
			}
		}
		Encode(.buf[:], [:+1])
		.buf[2] = ' '
		 := 3
There's an additional space after the 8th byte.
			.buf[3] = ' '
			 = 4
At the end of the line there's an extra space and the bar for the right column.
			.buf[3] = ' '
			.buf[4] = '|'
			 = 5
		}
		_,  = .w.Write(.buf[:])
		if  != nil {
			return
		}
		++
		.rightChars[.used] = toChar([])
		.used++
		.n++
		if .used == 16 {
			.rightChars[16] = '|'
			.rightChars[17] = '\n'
			_,  = .w.Write(.rightChars[:])
			if  != nil {
				return
			}
			.used = 0
		}
	}
	return
}

See the comments in Write() for the details of this format.
	if .closed {
		return
	}
	.closed = true
	if .used == 0 {
		return
	}
	.buf[0] = ' '
	.buf[1] = ' '
	.buf[2] = ' '
	.buf[3] = ' '
	.buf[4] = '|'
	 := .used
	for .used < 16 {
		 := 3
		if .used == 7 {
			 = 4
		} else if .used == 15 {
			 = 5
		}
		_,  = .w.Write(.buf[:])
		if  != nil {
			return
		}
		.used++
	}
	.rightChars[] = '|'
	.rightChars[+1] = '\n'
	_,  = .w.Write(.rightChars[:+2])
	return