github.com/machinebox/remoto@v0.1.2-0.20191024144331-eff21a7d321f/console/internal/id/id.go (about)

     1  // Package id is a pretty string to int64 converter for IDs in URLs.
     2  package id
     3  
     4  import (
     5  	"math/big"
     6  	"strconv"
     7  )
     8  
     9  var chars = []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
    10  
    11  // Itoa encodes an int64 into a string.
    12  func Itoa(val int64) string {
    13  	var result []byte
    14  	var index int
    15  	var strVal string
    16  	base := big.NewInt(int64(len(chars)))
    17  	a := big.NewInt(0)
    18  	b := big.NewInt(0)
    19  	c := big.NewInt(0)
    20  	d := big.NewInt(0)
    21  	exponent := 1
    22  	remaining := big.NewInt(val)
    23  	for remaining.Cmp(big.NewInt(0)) != 0 {
    24  		a.Exp(base, big.NewInt(int64(exponent)), nil) //16^1 = 16
    25  		b = b.Mod(remaining, a)                       //119 % 16 = 7 | 112 % 256 = 112
    26  		c = c.Exp(base, big.NewInt(int64(exponent-1)), nil)
    27  		d = d.Div(b, c)
    28  		strVal = d.String()
    29  		index, _ = strconv.Atoi(strVal)
    30  		result = append(result, chars[index])
    31  		remaining = remaining.Sub(remaining, b) //119 - 7 = 112 | 112 - 112 = 0
    32  		exponent = exponent + 1
    33  	}
    34  	return string(reverse(result))
    35  }
    36  
    37  // Atoi decodes a string into an int64.
    38  func Atoi(s string) int64 {
    39  	chars2 := reverse([]byte(s))
    40  	dictMap := make(map[byte]*big.Int)
    41  	j := 0
    42  	for _, val := range chars {
    43  		dictMap[val] = big.NewInt(int64(j))
    44  		j = j + 1
    45  	}
    46  	bi := big.NewInt(0)
    47  	base := big.NewInt(int64(len(chars)))
    48  	exponent := 0
    49  	b := big.NewInt(0)
    50  	intermed := big.NewInt(0)
    51  	for _, c := range chars2 {
    52  		a := dictMap[c]
    53  		intermed = intermed.Exp(base, big.NewInt(int64(exponent)), nil)
    54  		b = b.Mul(intermed, a)
    55  		bi = bi.Add(bi, b)
    56  		exponent = exponent + 1
    57  	}
    58  	return bi.Int64()
    59  }
    60  
    61  func reverse(bs []byte) []byte {
    62  	for i, j := 0, len(bs)-1; i < j; i, j = i+1, j-1 {
    63  		bs[i], bs[j] = bs[j], bs[i]
    64  	}
    65  	return bs
    66  }