@@ -10,7 +10,6 @@ import (
10
10
"errors"
11
11
"fmt"
12
12
"math"
13
- "strconv"
14
13
"strings"
15
14
)
16
15
@@ -224,16 +223,26 @@ func (h *HashID) EncodeInt64(numbers []int64) (string, error) {
224
223
// EncodeHex hashes a hexadecimal string to a string containing at least MinLength characters taken from the Alphabet.
225
224
// A hexadecimal string should not contain the 0x prefix.
226
225
// 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].
227
228
func (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" )
235
243
}
236
- nums = append (nums , int (n ))
244
+ // Each int is in range [16, 31]
245
+ nums [i ] = 0x10 + int (b )
237
246
}
238
247
239
248
return h .Encode (nums )
@@ -322,19 +331,23 @@ func (h *HashID) DecodeInt64WithError(hash string) ([]int64, error) {
322
331
323
332
// DecodeHex unhashes the string passed to a hexadecimal string.
324
333
// 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].
325
336
func (h * HashID ) DecodeHex (hash string ) (string , error ) {
326
337
numbers , err := h .DecodeInt64WithError (hash )
327
338
if err != nil {
328
339
return "" , err
329
340
}
330
341
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 ]
335
349
}
336
-
337
- return ret , nil
350
+ return string (b ), nil
338
351
}
339
352
340
353
func splitRunes (input , seps []rune ) [][]rune {
0 commit comments