// Package modhex implements modhex encoding and decoding. package modhex import ( "errors" "fmt" ) const modhexTable = "cbdefghijklnrtuv" var modhexMap map[byte]byte func init() { modhexMap = make(map[byte]byte) for i, v := range []byte(modhexTable) { modhexMap[v] = byte(i) } } // EncodedLen returns the length of an encoding of n source bytes. // Specifically, it returns n * 2. func EncodedLen(n int) int { return n * 2 } // Encode encodes src into EncodedLen(len(src)) bytes of dst. // It returns the number of bytes written to dst, but this is // always EncodedLen(len(src)). // Encode implements modhex encoding. func Encode(dst, src []byte) int { i := 0 for _, v := range src { dst[i] = modhexTable[v>>4] dst[i+1] = modhexTable[v&0x0f] i += 2 } return len(src) * 2 } // EncodeToString returns the modhex encoding of src. func EncodeToString(src []byte) string { // make a new slice to hold the encoded bytes dst := make([]byte, EncodedLen(len(src))) // encode it! Encode(dst, src) // return the encoded bytes as a string return string(dst) } // DecodedLen returns the length of a decoding of n source bytes. // Specifically, it returns n / 2. func DecodedLen(n int) int { return n / 2 } // Decode decodes src into DecodedLen(len(src)) bytes, returning // the actual number of bytes written to dst. // // Decode expects that src contains only modhex characters and that // src has an even length. // If the input is malformed, Decode returns the number // of bytes decoded before the error. func Decode(dst, src []byte) (int, error) { i, j := 0, 1 for ; j < len(src); j += 2 { a, ok := modhexMap[src[j-1]] if !ok { return i, fmt.Errorf("modhex: invalid byte: %#U", rune(src[j-1])) } b, ok := modhexMap[src[j]] if !ok { return i, fmt.Errorf("modhex: invalid byte: %#U", rune(src[j])) } dst[i] = (a << 4) | b i++ } if len(src)%2 == 1 { if _, ok := modhexMap[src[j-1]]; !ok { return i, fmt.Errorf("modhex: invalid byte: %#U", rune(src[j-1])) } return i, errors.New("modhex: odd length modhex string") } return i, nil } // DecodeString returns the bytes represesented by the modhex string s. // // Decode expects that s contains only modhex characters and that s // has an even length. // If the input is malformed, Decode returns the number // of bytes decoded before the error. func DecodeString(s string) ([]byte, error) { // convert the input string to an array of bytes src := []byte(s) // make a new slice to hold the decoded bytes dst := make([]byte, DecodedLen(len(src))) // decode it! n, err := Decode(dst, src) // return the decoded bytes along with any errors that may have occured return dst[:n], err }