/
base62.go
91 lines (73 loc) · 1.72 KB
/
base62.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package base62
import (
"encoding/binary"
"errors"
)
var (
// StdEncoding base62 standard encoder.
StdEncoding = MustNewEncoder(StdSource())
// stdSource base62 standard source string.
stdSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
)
// Encoder base62 encoder.
type Encoder struct {
encode [62]byte
decodeMap [256]int
}
// StdSource returns base62 standard source string.
func StdSource() string {
return stdSource
}
// MustNewEncoder must new a base62 encoder.
func MustNewEncoder(source string) *Encoder {
enc, err := NewEncoder(source)
if err != nil {
panic(err)
}
return enc
}
// NewEncoder new a base62 encoder.
func NewEncoder(source string) (*Encoder, error) {
if len(source) != 62 {
return nil, errors.New("base62: encoding source is not 62-bytes long")
}
enc := new(Encoder)
for i := range enc.decodeMap {
enc.decodeMap[i] = -1
}
for i := range source {
enc.encode[i] = source[i]
enc.decodeMap[enc.encode[i]] = i
}
return enc, nil
}
// Encode base62 encodes a int64 id.
func (enc *Encoder) Encode(id int64) string {
if id == 0 {
return string(enc.encode[:1])
}
bin := make([]byte, 0, binary.MaxVarintLen64)
for id > 0 {
bin = append(bin, enc.encode[id%62])
id /= 62
}
for i, j := 0, len(bin)-1; i < j; i, j = i+1, j-1 {
bin[i], bin[j] = bin[j], bin[i]
}
return string(bin)
}
// Decode base62 decodes a string id.
func (enc *Encoder) Decode(id string) (int64, error) {
if id == "" {
return 0, errors.New("base62: decoding id should not be empty")
}
var n int64
for i := range id {
u := enc.decodeMap[id[i]]
if u < 0 {
return 0, errors.New("base62: invalid decoding character - " + string(id[i]))
}
n = n*62 + int64(u)
}
return n, nil
}