package base62 import ( "bytes" "errors" "github.com/samber/lo" ) type Base62 struct { characters []byte // base62 编码规则 charactersMap map[byte]int // base62 编码规则 } func GetInstance() *Base62 { b62 := &Base62{} b62.SetCharacters([]byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) return b62 } func (base62 *Base62) SetCharacters(characters []byte) (*Base62, error) { characters = lo.FindUniques(characters) charactersMap := make(map[byte]int) if len(characters) != 62 { return nil, errors.New("Invalid characters") } for i, v := range characters { charactersMap[v] = i } base62.characters = characters base62.charactersMap = charactersMap return base62, nil } // Encode function receives a byte slice and encodes it to a string using the alphabet provided func (base62 *Base62) Encode(source []byte) string { if len(source) == 0 { return "" } digits := []int{0} for i := 0; i < len(source); i++ { carry := int(source[i]) for j := 0; j < len(digits); j++ { carry += digits[j] << 8 digits[j] = carry % 62 carry = carry / 62 } for carry > 0 { digits = append(digits, carry%62) carry = carry / 62 } } var res bytes.Buffer for k := 0; source[k] == 0 && k < len(source)-1; k++ { res.WriteByte(base62.characters[0]) } for q := len(digits) - 1; q >= 0; q-- { res.WriteByte(base62.characters[digits[q]]) } return res.String() } // Decode function decodes a string previously obtained from Encode, using the same alphabet and returns a byte slice // In case the input is not valid an arror will be returned func (base62 *Base62) Decode(source string) ([]byte, error) { if len(source) == 0 { return []byte{}, nil } runes := []byte(source) bytes := []byte{0} for i := 0; i < len(runes); i++ { value, ok := base62.charactersMap[runes[i]] if !ok { return nil, errors.New("Non Base Character") } carry := int(value) for j := 0; j < len(bytes); j++ { carry += int(bytes[j]) * 62 bytes[j] = byte(carry & 0xff) carry >>= 8 } for carry > 0 { bytes = append(bytes, byte(carry&0xff)) carry >>= 8 } } for k := 0; runes[k] == base62.characters[0] && k < len(runes)-1; k++ { bytes = append(bytes, 0) } // Reverse bytes for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 { bytes[i], bytes[j] = bytes[j], bytes[i] } return bytes, nil }