@@ -10,7 +10,6 @@ import (
1010 "errors"
1111 "fmt"
1212 "math"
13- "strconv"
1413 "strings"
1514)
1615
@@ -224,16 +223,26 @@ func (h *HashID) EncodeInt64(numbers []int64) (string, error) {
224223// EncodeHex hashes a hexadecimal string to a string containing at least MinLength characters taken from the Alphabet.
225224// A hexadecimal string should not contain the 0x prefix.
226225// Use DecodeHex using the same Alphabet and Salt to get back the hexadecimal string.
226+ //
227+ // Each hex nibble is encoded as an integer in range [16, 31].
227228func (h * HashID ) EncodeHex (hex string ) (string , error ) {
228- chars := []rune (hex )
229- nums := []int {}
230-
231- for _ , s := range chars {
232- n , err := strconv .ParseInt (fmt .Sprintf ("1%s" , string (s )), 16 , 64 )
233- if err != nil {
234- return "" , err
229+ nums := make ([]int , len (hex ))
230+
231+ for i := 0 ; i < len (hex ); i ++ {
232+ b := hex [i ]
233+ switch {
234+ case (b >= '0' ) && (b <= '9' ):
235+ b -= '0'
236+ case (b >= 'a' ) && (b <= 'f' ):
237+ b -= 'a' - 'A'
238+ fallthrough
239+ case (b >= 'A' ) && (b <= 'F' ):
240+ b -= ('A' - 0xA )
241+ default :
242+ return "" , errors .New ("invalid hex digit" )
235243 }
236- nums = append (nums , int (n ))
244+ // Each int is in range [16, 31]
245+ nums [i ] = 0x10 + int (b )
237246 }
238247
239248 return h .Encode (nums )
@@ -322,19 +331,23 @@ func (h *HashID) DecodeInt64WithError(hash string) ([]int64, error) {
322331
323332// DecodeHex unhashes the string passed to a hexadecimal string.
324333// It is symmetric with EncodeHex if the Alphabet and Salt are the same ones which were used to hash.
334+ //
335+ // Each hex nibble is decoded from an integer in range [16, 31].
325336func (h * HashID ) DecodeHex (hash string ) (string , error ) {
326337 numbers , err := h .DecodeInt64WithError (hash )
327338 if err != nil {
328339 return "" , err
329340 }
330341
331- ret := ""
332- for _ , n := range numbers {
333- nHex := fmt .Sprintf ("%X" , n )
334- ret = strings .ToLower (fmt .Sprintf ("%s%s" , ret , nHex [1 :len (nHex )]))
342+ const hex = "0123456789abcdef"
343+ b := make ([]byte , len (numbers ))
344+ for i , n := range numbers {
345+ if n < 0x10 || n > 0x1f {
346+ return "" , errors .New ("invalid number" )
347+ }
348+ b [i ] = hex [n - 0x10 ]
335349 }
336-
337- return ret , nil
350+ return string (b ), nil
338351}
339352
340353func splitRunes (input , seps []rune ) [][]rune {
0 commit comments