79 lines
1.9 KiB
Go
79 lines
1.9 KiB
Go
package shortid
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/binary"
|
|
"errors"
|
|
)
|
|
|
|
// EncodeID 将 uint64 雪花 ID 编码为短字符串(推荐)
|
|
// 使用 Base64 URL 安全编码,结果长度约 11 字符
|
|
func EncodeID(id uint64) string {
|
|
buf := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(buf, id)
|
|
return base64.RawURLEncoding.EncodeToString(buf)
|
|
}
|
|
|
|
// DecodeID 解码短字符串为 uint64
|
|
func DecodeID(s string) (uint64, error) {
|
|
data, err := base64.RawURLEncoding.DecodeString(s)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if len(data) > 8 {
|
|
return 0, errors.New("数据过长")
|
|
}
|
|
|
|
// 补齐到 8 字节
|
|
buf := make([]byte, 8)
|
|
copy(buf[8-len(data):], data)
|
|
return binary.BigEndian.Uint64(buf), nil
|
|
}
|
|
|
|
// EncodeIDCompact 紧凑编码(去除前导零,适合小 ID)
|
|
func EncodeIDCompact(id uint64) string {
|
|
buf := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(buf, id)
|
|
|
|
// 去除前导零
|
|
trimmed := bytes.TrimLeft(buf, "\x00")
|
|
if len(trimmed) == 0 {
|
|
trimmed = []byte{0}
|
|
}
|
|
|
|
return base64.RawURLEncoding.EncodeToString(trimmed)
|
|
}
|
|
|
|
// DecodeIDCompact 解码紧凑编码
|
|
func DecodeIDCompact(s string) (uint64, error) {
|
|
data, err := base64.RawURLEncoding.DecodeString(s)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// 还原到 8 字节
|
|
buf := make([]byte, 8)
|
|
copy(buf[8-len(data):], data)
|
|
return binary.BigEndian.Uint64(buf), nil
|
|
}
|
|
|
|
// GenerateMeshSeedPrefix 生成 MeshSeed TXT 记录前缀
|
|
// 格式:_meshray.{encoded_id}
|
|
func GenerateMeshSeedPrefix(networkID uint64) string {
|
|
shortID := EncodeID(networkID)
|
|
return "_meshray." + shortID
|
|
}
|
|
|
|
// ExtractNetworkID 从 TXT 记录前缀提取网络 ID
|
|
func ExtractNetworkID(prefix string) (uint64, error) {
|
|
// 格式:_meshray.{encoded_id}
|
|
if len(prefix) <= 9 || prefix[:9] != "_meshray." {
|
|
return 0, errors.New("非标准前缀格式")
|
|
}
|
|
|
|
encodedID := prefix[9:] // 提取 _meshray. 后面的部分
|
|
return DecodeID(encodedID)
|
|
}
|