Files
ag_toolsbox/serialize/base36/base36.go

109 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package base36
import (
"fmt"
"math/big"
"strings"
)
// Encode 将字节数据编码为Base36字符串(大写),使用=作为padding字符
func Encode(src []byte) string {
if len(src) == 0 {
return ""
}
// 将字节转换为big.Int
num := new(big.Int).SetBytes(src)
// 如果输入为全零字节,则直接返回"0"
if num.Cmp(big.NewInt(0)) == 0 {
return "0"
}
// 进行Base36编码
var result strings.Builder
base := big.NewInt(36)
zero := big.NewInt(0)
remainder := new(big.Int)
// 重复除以36获取余数作为字符
for num.Cmp(zero) > 0 {
num.DivMod(num, base, remainder)
digit := remainder.Int64()
if digit < 10 {
result.WriteString(fmt.Sprintf("%d", digit))
} else {
result.WriteString(fmt.Sprintf("%c", 'A'+digit-10))
}
}
// 反转字符串,因为我们是从低位开始计算的
encoded := result.String()
runes := []rune(encoded)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
// Decode 将Base36字符串(可为任意大小写)解码为字节数组
func Decode(src string) ([]byte, error) {
if src == "" {
return []byte{}, nil
}
// 移除padding字符
src = strings.ReplaceAll(src, "=", "")
src = strings.ToUpper(src)
// 使用big.Int进行解码
num := big.NewInt(0)
base := big.NewInt(36)
for _, char := range src {
var digit int64
switch {
case char >= '0' && char <= '9':
digit = int64(char - '0')
case char >= 'A' && char <= 'Z':
digit = int64(char - 'A' + 10)
default:
return nil, fmt.Errorf("invalid character %c in base36 string", char)
}
num.Mul(num, base)
num.Add(num, big.NewInt(digit))
}
// 转换为字节数组
return num.Bytes(), nil
}
// EncodeToString 是Encode的别名用于保持与标准库一致的命名
func EncodeToString(src []byte) string {
return Encode(src)
}
// DecodeString 是Decode的别名用于保持与标准库一致的命名
func DecodeString(src string) ([]byte, error) {
return Decode(src)
}
// EncodeInt64 将int64转换为Base36字符串
func EncodeInt64(num int64) string {
return EncodeToString(big.NewInt(num).Bytes())
}
// DecodeToInt64 将Base36字符串解码为int64
func DecodeToInt64(src string) (int64, error) {
bytes, err := DecodeString(src)
if err != nil {
return 0, err
}
return new(big.Int).SetBytes(bytes).Int64(), nil
}