bitbucket.org/ai69/amoy@v0.2.3/base36.go (about) 1 package amoy 2 3 // Migrate from https://github.com/martinlindhe/base36/blob/master/base36.go 4 5 import ( 6 "math/big" 7 "strings" 8 ) 9 10 var ( 11 bigRadix = big.NewInt(36) 12 bigZero = big.NewInt(0) 13 base36 = []byte("0123456789abcdefghijklmnopqrstuvwxyz") 14 uint8Index = []uint64{ 15 0, 16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 21 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 22 0, 0, 0, 0, 10, 11, 12, 13, 14, 23 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 25 35, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 26 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 27 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 28 34, 35, 0, 0, 0, 0, 0, 0, 0, 0, 29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41 0, 0, 0, 0, 0, // 256 42 } 43 pow36Index = []uint64{ 44 1, 36, 1296, 46656, 1679616, 60466176, 45 2176782336, 78364164096, 2821109907456, 46 101559956668416, 3656158440062976, 47 131621703842267136, 4738381338321616896, 48 9223372036854775808, 49 } 50 ) 51 52 // EncodeBytesAsBase36Bytes encodes a byte slice to base36. 53 func EncodeBytesAsBase36Bytes(b []byte) []byte { 54 x := new(big.Int) 55 x.SetBytes(b) 56 57 answer := make([]byte, 0, len(b)*136/100) 58 for x.Cmp(bigZero) > 0 { 59 mod := new(big.Int) 60 x.DivMod(x, bigRadix, mod) 61 answer = append(answer, base36[mod.Int64()]) 62 } 63 64 // leading zero bytes 65 for _, i := range b { 66 if i != 0 { 67 break 68 } 69 answer = append(answer, base36[0]) 70 } 71 72 // reverse 73 alen := len(answer) 74 for i := 0; i < alen/2; i++ { 75 answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i] 76 } 77 78 return answer 79 } 80 81 // EncodeBytesAsBase36 encodes a byte slice to base36 string. 82 func EncodeBytesAsBase36(b []byte) string { 83 return string(EncodeBytesAsBase36Bytes(b)) 84 } 85 86 // DecodeBase36ToBytes decodes a base36 string to a byte slice, using alphabet. 87 func DecodeBase36ToBytes(b string) []byte { 88 alphabet := string(base36) 89 answer := big.NewInt(0) 90 j := big.NewInt(1) 91 92 for i := len(b) - 1; i >= 0; i-- { 93 tmp := strings.IndexAny(alphabet, string(b[i])) 94 if tmp == -1 { 95 return []byte("") 96 } 97 idx := big.NewInt(int64(tmp)) 98 tmp1 := big.NewInt(0) 99 tmp1.Mul(j, idx) 100 101 answer.Add(answer, tmp1) 102 j.Mul(j, bigRadix) 103 } 104 105 tmpval := answer.Bytes() 106 107 var numZeros int 108 for numZeros = 0; numZeros < len(b); numZeros++ { 109 if b[numZeros] != alphabet[0] { 110 break 111 } 112 } 113 flen := numZeros + len(tmpval) 114 val := make([]byte, flen, flen) 115 copy(val[numZeros:], tmpval) 116 117 return val 118 }