diff --git a/modhex.go b/modhex.go index 92cfdc1..74e15e6 100644 --- a/modhex.go +++ b/modhex.go @@ -67,6 +67,18 @@ func DecodedLen(n int) int { return n / 2 } +// ErrLength reports an attempt to decode an odd-length input using Decode +// or DecodeString. +var ErrLength = errors.New("modhex: odd length modhex string") + +// InvalidByteError values describe errors resulting from an invalid byte in a +// hex string. +type InvalidByteError byte + +func (e InvalidByteError) Error() string { + return fmt.Sprintf("modhex: invalid byte: %#U", rune(e)) +} + // Decode decodes src into DecodedLen(len(src)) bytes, returning // the actual number of bytes written to dst. // @@ -78,12 +90,12 @@ func Decode(dst, src []byte) (int, error) { 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])) + return i, InvalidByteError(src[j-1]) } b, ok := modhexMap[src[j]] if !ok { - return i, fmt.Errorf("modhex: invalid byte: %#U", rune(src[j])) + return i, InvalidByteError(src[j]) } dst[i] = (a << 4) | b @@ -92,10 +104,10 @@ func Decode(dst, src []byte) (int, error) { 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, InvalidByteError(src[j-1]) } - return i, errors.New("modhex: odd length modhex string") + return i, ErrLength } return i, nil diff --git a/modhex_test.go b/modhex_test.go index f3a877a..edcd96f 100644 --- a/modhex_test.go +++ b/modhex_test.go @@ -1,60 +1,89 @@ package modhex import ( - "encoding/hex" - "strings" + "bytes" "testing" ) -type test struct { - hex string - modhex string +type encDecTest struct { + enc string + dec []byte } -func TestEncodeHexDecodeHex(t *testing.T) { - var tests = []test{ - { - modhex: "dteffuje", - hex: "2d344e83", - }, - - { - modhex: "DTEFFUJE", - hex: "2d344e83", - }, - - { - modhex: "dTeFfUjE", - hex: "2d344e83", - }, - - { - modhex: "hknhfjbrjnlnldnhcujvddbikngjrtgh", - hex: "69b6481c8baba2b60e8f22179b58cd56", - }, - - { - modhex: "urtubjtnuihvntcreeeecvbregfjibtn", - hex: "ecde18dbe76fbd0c33330f1c354871db", - }, +var encDecTests = []encDecTest{ + {"", []byte{}}, + {"dteffuje", []byte{0x2d, 0x34, 0x4e, 0x83}}, + { + "hknhfjbrjnlnldnhcujvddbikngjrtgh", + []byte{0x69, 0xb6, 0x48, 0x1c, 0x8b, 0xab, + 0xa2, 0xb6, 0x0e, 0x8f, 0x22, 0x17, + 0x9b, 0x58, 0xcd, 0x56}, + }, + { + "urtubjtnuihvntcreeeecvbregfjibtn", + []byte{0xec, 0xde, 0x18, 0xdb, 0xe7, 0x6f, + 0xbd, 0x0c, 0x33, 0x33, 0x0f, 0x1c, + 0x35, 0x48, 0x71, 0xdb}, + }, +} + +func TestEncode(t *testing.T) { + for i, test := range encDecTests { + dst := make([]byte, EncodedLen(len(test.dec))) + + n := Encode(dst, test.dec) + + if n != len(dst) { + t.Errorf("#%d: bad return value: got %d want: %d", i, n, len(dst)) + } + + if string(dst) != test.enc { + t.Errorf("#%d: got: %#v want %#v", i, dst, []byte(test.enc)) + } } +} + +func TestDecode(t *testing.T) { + for i, test := range encDecTests { + dst := make([]byte, DecodedLen(len(test.enc))) - for _, tc := range tests { - src, _ := hex.DecodeString(tc.hex) - modhex := EncodeToString(src) + n, err := Decode(dst, []byte(test.enc)) - if modhex != strings.ToLower(modhex) { - t.Errorf("Encode Incorrect: Actual: %s; Expected: %s\n", modhex, tc.modhex) + if err != nil { + t.Errorf("#%d: unexpected err value: %s", i, err) + continue } - hexBytes, err := DecodeString(tc.modhex) + if n != len(dst) { + t.Errorf("#%d: bad return value got: %d want:%d", i, n, len(dst)) + } + + if !bytes.Equal(dst, test.dec) { + t.Errorf("#%d: got %#v want: %#v", i, dst, test.dec) + } + } +} + +func TestEncodeToString(t *testing.T) { + for i, test := range encDecTests { + s := EncodeToString(test.dec) + if s != test.enc { + t.Errorf("#%d: got: %s want: %s", i, s, test.enc) + } + } +} + +func TestDecodeString(t *testing.T) { + for i, test := range encDecTests { + dst, err := DecodeString(test.enc) + if err != nil { - t.Error(err) + t.Errorf("#%d: unexpected err value: %s", i, err) + continue } - hexStr := hex.EncodeToString(hexBytes) - if hexStr != tc.hex { - t.Errorf("Decode Incorrect: Actual: %s; Expected: %s\n", hexStr, tc.hex) + if !bytes.Equal(dst, test.dec) { + t.Errorf("#%d: got %#v want: %#v", i, dst, test.dec) } } }