// 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. // This package implements hexadecimal encoding and decoding. package hex import ( "os"; "strconv"; "strings"; ) const hextable = "0123456789abcdef" // EncodedLen returns the length of an encoding of n source bytes. func EncodedLen(n int) int { return n * 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 Encode(dst, src []byte) int { for i, v := range src { dst[i*2] = hextable[v>>4]; dst[i*2+1] = hextable[v&0x0f]; } return len(src) * 2; } // OddLengthInputError results from decoding an odd length slice. type OddLengthInputError struct{} func (OddLengthInputError) String() string { return "odd length hex string" } // InvalidHexCharError results from finding an invalid character in a hex string. type InvalidHexCharError byte func (e InvalidHexCharError) String() string { return "invalid hex char: " + strconv.Itoa(int(e)) } func DecodedLen(x int) int { return x / 2 } // Decode decodes src into DecodedLen(len(src)) bytes, returning the actual // number of bytes written to dst. // // If Decode encounters invalid input, it returns an OddLengthInputError or an // InvalidHexCharError. func Decode(dst, src []byte) (int, os.Error) { if len(src)%2 == 1 { return 0, OddLengthInputError{} } for i := 0; i < len(src)/2; i++ { a, ok := fromHexChar(src[i*2]); if !ok { return 0, InvalidHexCharError(src[i*2]) } b, ok := fromHexChar(src[i*2+1]); if !ok { return 0, InvalidHexCharError(src[i*2+1]) } dst[i] = (a << 4) | b; } return len(src) / 2, nil; } // fromHexChar converts a hex character into its value and a success flag. func fromHexChar(c byte) (byte, bool) { switch { case 0 <= c && c <= '9': return c - '0', true case 'a' <= c && c <= 'f': return c - 'a' + 10, true case 'A' <= c && c <= 'F': return c - 'A' + 10, true } return 0, false; } // EncodeToString returns the hexadecimal encoding of src. func EncodeToString(src []byte) string { dst := make([]byte, EncodedLen(len(src))); Encode(dst, src); return string(dst); } // DecodeString returns the bytes represented by the hexadecimal string s. func DecodeString(s string) ([]byte, os.Error) { src := strings.Bytes(s); dst := make([]byte, DecodedLen(len(src))); _, err := Decode(dst, src); if err != nil { return nil, err } return dst, nil; }