Skip to content

Commit

Permalink
Merge pull request #46 from dolmen-go/fix-EncodeHex
Browse files Browse the repository at this point in the history
Fix EncodeHex/DecodeHex
  • Loading branch information
speps authored Jun 26, 2018
2 parents d5e694a + b97bdbf commit ad304c6
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 15 deletions.
43 changes: 28 additions & 15 deletions hashids.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"math"
"strconv"
"strings"
)

Expand Down Expand Up @@ -224,16 +223,26 @@ func (h *HashID) EncodeInt64(numbers []int64) (string, error) {
// EncodeHex hashes a hexadecimal string to a string containing at least MinLength characters taken from the Alphabet.
// A hexadecimal string should not contain the 0x prefix.
// Use DecodeHex using the same Alphabet and Salt to get back the hexadecimal string.
//
// Each hex nibble is encoded as an integer in range [16, 31].
func (h *HashID) EncodeHex(hex string) (string, error) {
chars := []rune(hex)
nums := []int{}

for _, s := range chars {
n, err := strconv.ParseInt(fmt.Sprintf("1%s", string(s)), 16, 64)
if err != nil {
return "", err
nums := make([]int, len(hex))

for i := 0; i < len(hex); i++ {
b := hex[i]
switch {
case (b >= '0') && (b <= '9'):
b -= '0'
case (b >= 'a') && (b <= 'f'):
b -= 'a' - 'A'
fallthrough
case (b >= 'A') && (b <= 'F'):
b -= ('A' - 0xA)
default:
return "", errors.New("invalid hex digit")
}
nums = append(nums, int(n))
// Each int is in range [16, 31]
nums[i] = 0x10 + int(b)
}

return h.Encode(nums)
Expand Down Expand Up @@ -322,19 +331,23 @@ func (h *HashID) DecodeInt64WithError(hash string) ([]int64, error) {

// DecodeHex unhashes the string passed to a hexadecimal string.
// It is symmetric with EncodeHex if the Alphabet and Salt are the same ones which were used to hash.
//
// Each hex nibble is decoded from an integer in range [16, 31].
func (h *HashID) DecodeHex(hash string) (string, error) {
numbers, err := h.DecodeInt64WithError(hash)
if err != nil {
return "", err
}

ret := ""
for _, n := range numbers {
nHex := fmt.Sprintf("%X", n)
ret = strings.ToLower(fmt.Sprintf("%s%s", ret, nHex[1:len(nHex)]))
const hex = "0123456789abcdef"
b := make([]byte, len(numbers))
for i, n := range numbers {
if n < 0x10 || n > 0x1f {
return "", errors.New("invalid number")
}
b[i] = hex[n-0x10]
}

return ret, nil
return string(b), nil
}

func splitRunes(input, seps []rune) [][]rune {
Expand Down
5 changes: 5 additions & 0 deletions hashids_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ func TestEncodeDecodeHex(t *testing.T) {
t.Fatal(err)
}

const expected = "qmTqfesOIqHrsoCYf9UkFZixSKuBT4umuruXuMiDsVsbSrfV"
if hash != expected {
t.Fatalf("got %q, expected %q", hash, expected)
}

dec, err := hid.DecodeHex(hash)
if err != nil {
t.Fatal(err)
Expand Down

0 comments on commit ad304c6

Please sign in to comment.