2026-04-22 13:48:27 +08:00
|
|
|
package encoding
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
2026-06-08 21:19:24 +08:00
|
|
|
|
|
|
|
|
"apigo.cc/go/cast"
|
2026-06-22 00:44:59 +08:00
|
|
|
"apigo.cc/go/rand"
|
2026-04-22 13:48:27 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// IntEncoder 提供整数与字节切片之间的自定义进制转换
|
|
|
|
|
type IntEncoder struct {
|
|
|
|
|
radix uint8
|
|
|
|
|
digits string
|
|
|
|
|
decodeMap [256]int
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 22:18:52 +08:00
|
|
|
// EncodeInt 将整数转换为字节切片
|
|
|
|
|
func (enc *IntEncoder) EncodeInt(u uint64) []byte {
|
|
|
|
|
return enc.AppendInt(nil, u)
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AppendInt 将整数追加到已有字节切片中
|
|
|
|
|
func (enc *IntEncoder) AppendInt(buf []byte, u uint64) []byte {
|
|
|
|
|
if buf == nil {
|
|
|
|
|
buf = make([]byte, 0)
|
|
|
|
|
}
|
|
|
|
|
radix := uint64(enc.radix)
|
|
|
|
|
for u >= radix {
|
|
|
|
|
q := u / radix
|
|
|
|
|
buf = append(buf, enc.digits[uint(u-q*radix)])
|
|
|
|
|
u = q
|
|
|
|
|
}
|
|
|
|
|
buf = append(buf, enc.digits[uint(u)])
|
|
|
|
|
return buf
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-22 00:44:59 +08:00
|
|
|
// FillInt 使用随机字符序列填充数据至指定长度,高并发下具备零锁极速随机性能,就地修改并返回
|
2026-06-08 21:19:24 +08:00
|
|
|
func (enc *IntEncoder) FillInt(data any, length int) []byte {
|
|
|
|
|
buf := cast.To[[]byte](data)
|
2026-04-22 13:48:27 +08:00
|
|
|
currLen := len(buf)
|
|
|
|
|
if currLen >= length {
|
|
|
|
|
return buf
|
|
|
|
|
}
|
|
|
|
|
if cap(buf) < length {
|
|
|
|
|
newBuf := make([]byte, currLen, length)
|
|
|
|
|
copy(newBuf, buf)
|
|
|
|
|
buf = newBuf
|
|
|
|
|
}
|
|
|
|
|
buf = buf[:length]
|
2026-05-01 13:41:06 +08:00
|
|
|
radix := int(enc.radix)
|
2026-04-22 13:48:27 +08:00
|
|
|
for i := currLen; i < length; i++ {
|
2026-06-22 00:44:59 +08:00
|
|
|
// 使用 go/rand 零锁随机性能从 digits 中抽取字符填充
|
|
|
|
|
rnd := rand.FastInt(0, radix-1)
|
|
|
|
|
buf[i] = enc.digits[rnd]
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
return buf
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-22 00:44:59 +08:00
|
|
|
// FoldInt 使用编码器的字符集模加法,将超出 length 的尾部字节折叠到前 length 字节中,就地修改并截断返回
|
|
|
|
|
func (enc *IntEncoder) FoldInt(buf []byte, length int) []byte {
|
|
|
|
|
size := len(buf)
|
|
|
|
|
if size <= length {
|
|
|
|
|
return buf
|
|
|
|
|
}
|
|
|
|
|
radix := int(enc.radix)
|
|
|
|
|
for i := length; i < size; i++ {
|
|
|
|
|
p1 := enc.decodeMap[buf[i%length]]
|
|
|
|
|
p2 := enc.decodeMap[buf[i]]
|
|
|
|
|
if p1 < 0 {
|
|
|
|
|
p1 = 0
|
|
|
|
|
}
|
|
|
|
|
if p2 < 0 {
|
|
|
|
|
p2 = 0
|
|
|
|
|
}
|
|
|
|
|
newP := (p1 + p2) % radix
|
|
|
|
|
buf[i%length] = enc.digits[newP]
|
|
|
|
|
}
|
|
|
|
|
return buf[:length]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ExchangeInt 对数据进行位置交替重排,就地修改并返回
|
2026-06-08 21:19:24 +08:00
|
|
|
func (enc *IntEncoder) ExchangeInt(data any) []byte {
|
|
|
|
|
buf := cast.To[[]byte](data)
|
2026-04-22 13:48:27 +08:00
|
|
|
size := len(buf)
|
|
|
|
|
if size <= 1 {
|
|
|
|
|
return buf
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-22 00:44:59 +08:00
|
|
|
var buf2 []byte
|
|
|
|
|
if size <= 20 {
|
|
|
|
|
var tmp [20]byte // 栈分配:极致性能,零垃圾回收负担
|
|
|
|
|
buf2 = tmp[:size]
|
|
|
|
|
} else {
|
|
|
|
|
buf2 = make([]byte, size)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-22 13:48:27 +08:00
|
|
|
buf2_i := 0
|
|
|
|
|
buf2_ai := 0
|
|
|
|
|
buf2_ri := size - 1
|
|
|
|
|
for i := 0; i < size; i++ {
|
|
|
|
|
if i%2 == 0 {
|
|
|
|
|
buf2[buf2_i] = buf[buf2_ri]
|
|
|
|
|
buf2_ri--
|
|
|
|
|
} else {
|
|
|
|
|
buf2[buf2_i] = buf[buf2_ai]
|
|
|
|
|
buf2_ai++
|
|
|
|
|
}
|
|
|
|
|
buf2_i++
|
|
|
|
|
}
|
2026-06-22 00:44:59 +08:00
|
|
|
|
|
|
|
|
// 将打乱后的数据拷贝回原切片,实现“原地修改”
|
|
|
|
|
copy(buf, buf2)
|
|
|
|
|
return buf
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-22 00:44:59 +08:00
|
|
|
// HashInt 双向非线性渐进式置换混淆,原地修改并返回,所有值保持在 radix 字符集内
|
|
|
|
|
func (enc *IntEncoder) HashInt(buf []byte) []byte {
|
|
|
|
|
if len(buf) == 0 {
|
|
|
|
|
return buf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第一轮:正向传播(左向右)
|
|
|
|
|
prevP := (len(buf) * 17) % int(enc.radix)
|
|
|
|
|
for i, c := range buf {
|
|
|
|
|
p := enc.decodeMap[c]
|
|
|
|
|
if p < 0 {
|
|
|
|
|
p = 0
|
|
|
|
|
}
|
|
|
|
|
p = (prevP + p) % int(enc.radix)
|
|
|
|
|
buf[i] = enc.digits[p]
|
|
|
|
|
prevP = OrderedIntEncoder.decodeMap[DefaultIntEncoder.digits[p]]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第二轮:反向传播(右向左),回传差异实现全局雪崩扩散
|
|
|
|
|
prevP = (len(buf) * 31) % int(enc.radix)
|
|
|
|
|
for i := len(buf) - 1; i >= 0; i-- {
|
|
|
|
|
p := enc.decodeMap[buf[i]]
|
|
|
|
|
if p < 0 {
|
|
|
|
|
p = 0
|
|
|
|
|
}
|
|
|
|
|
p = (prevP + p) % int(enc.radix)
|
|
|
|
|
buf[i] = enc.digits[p]
|
|
|
|
|
prevP = OrderedIntEncoder.decodeMap[DefaultIntEncoder.digits[p]]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return buf
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-08 21:19:24 +08:00
|
|
|
// DecodeInt 从数据解码为整数
|
|
|
|
|
func (enc *IntEncoder) DecodeInt(data any) uint64 {
|
|
|
|
|
buf := cast.To[[]byte](data)
|
2026-04-22 13:48:27 +08:00
|
|
|
radix := uint64(enc.radix)
|
|
|
|
|
if buf == nil {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
var n uint64 = 0
|
|
|
|
|
for i := len(buf) - 1; i >= 0; i-- {
|
|
|
|
|
p := enc.decodeMap[buf[i]]
|
|
|
|
|
if p >= 0 {
|
|
|
|
|
n = n*radix + uint64(p)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewIntEncoder 创建一个新的整数编码器
|
|
|
|
|
func NewIntEncoder(digits string, radix uint8) (*IntEncoder, error) {
|
|
|
|
|
if len(digits) < int(radix) {
|
2026-05-01 13:41:06 +08:00
|
|
|
return nil, errors.New("int encoder digits length is less than radix")
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e := IntEncoder{digits: digits, radix: radix, decodeMap: [256]int{}}
|
|
|
|
|
for i := 0; i < 256; i++ {
|
|
|
|
|
e.decodeMap[i] = -1
|
|
|
|
|
}
|
2026-05-01 13:41:06 +08:00
|
|
|
|
|
|
|
|
for i := 0; i < int(radix); i++ {
|
|
|
|
|
d := digits[i]
|
|
|
|
|
if e.decodeMap[d] != -1 {
|
|
|
|
|
return nil, errors.New("int encoder digits is repeated: " + digits)
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
2026-05-01 13:41:06 +08:00
|
|
|
e.decodeMap[d] = i
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &e, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 默认编码器实例
|
|
|
|
|
var DefaultIntEncoder, _ = NewIntEncoder("9ukH1grX75TQS6LzpFAjIivsdZoO0mc8NBwnyYDhtMWEC2V3KaGxfJRPqe4lbU", 62)
|
|
|
|
|
var OrderedIntEncoder, _ = NewIntEncoder("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 62)
|
|
|
|
|
|
2026-06-08 22:18:52 +08:00
|
|
|
// EncodeInt 使用默认编码器将整数转换为字节切片
|
|
|
|
|
func EncodeInt(u uint64) []byte {
|
2026-06-08 21:19:24 +08:00
|
|
|
return DefaultIntEncoder.EncodeInt(u)
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AppendInt 使用默认编码器将整数追加到已有字节切片中
|
|
|
|
|
func AppendInt(buf []byte, u uint64) []byte {
|
|
|
|
|
return DefaultIntEncoder.AppendInt(buf, u)
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-08 21:19:24 +08:00
|
|
|
// DecodeInt 使用默认编码器从数据解码为整数
|
|
|
|
|
func DecodeInt(data any) uint64 {
|
|
|
|
|
return DefaultIntEncoder.DecodeInt(data)
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-08 21:19:24 +08:00
|
|
|
// ExchangeInt 使用默认编码器对数据进行位置交替重排
|
|
|
|
|
func ExchangeInt(data any) []byte {
|
|
|
|
|
return DefaultIntEncoder.ExchangeInt(data)
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-22 00:44:59 +08:00
|
|
|
// HashInt 对数据进行渐进式置换混淆
|
|
|
|
|
func HashInt(buf []byte) []byte {
|
|
|
|
|
return DefaultIntEncoder.HashInt(buf)
|
2026-04-22 13:48:27 +08:00
|
|
|
}
|
2026-05-01 13:41:06 +08:00
|
|
|
|
2026-06-08 21:19:24 +08:00
|
|
|
// FillInt 使用默认编码器填充数据至指定长度
|
|
|
|
|
func FillInt(data any, length int) []byte {
|
|
|
|
|
return DefaultIntEncoder.FillInt(data, length)
|
2026-05-01 13:41:06 +08:00
|
|
|
}
|