encoding/int_encoder.go

150 lines
3.4 KiB
Go

package encoding
import (
"crypto/hmac"
"crypto/sha512"
"errors"
)
// IntEncoder 提供整数与字节切片之间的自定义进制转换
type IntEncoder struct {
radix uint8
digits string
decodeMap [256]int
}
// EncodeInt 将整数转换为字节切片
func (enc *IntEncoder) EncodeInt(u uint64) []byte {
return enc.AppendInt(nil, u)
}
// 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
}
// FillInt 使用随机字符填充字节切片至指定长度
func (enc *IntEncoder) FillInt(buf []byte, length int) []byte {
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]
radix := uint(enc.radix)
for i := currLen; i < length; i++ {
buf[i] = enc.digits[i%int(radix)]
}
return buf
}
// ExchangeInt 对字节切片进行位置置换混淆
func (enc *IntEncoder) ExchangeInt(buf []byte) []byte {
size := len(buf)
if size <= 1 {
return buf
}
buf2 := make([]byte, size)
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++
}
return buf2
}
// HashInt 对字节切片进行 HMAC-SHA512 哈希
func (enc *IntEncoder) HashInt(data []byte, key []byte) []byte {
hash := hmac.New(sha512.New, key)
hash.Write(data)
return hash.Sum([]byte{})
}
// DecodeInt 从字节切片解码为整数
func (enc *IntEncoder) DecodeInt(buf []byte) uint64 {
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) {
return nil, errors.New("int encoder digits is bad")
}
e := IntEncoder{digits: digits, radix: radix, decodeMap: [256]int{}}
for i := 0; i < 256; i++ {
e.decodeMap[i] = -1
}
m := map[int32]bool{}
for i, d := range digits {
e.decodeMap[digits[i]] = i
if m[d] {
return nil, errors.New("int encoder digits is repeated " + digits)
}
m[d] = true
}
return &e, nil
}
// 默认编码器实例
var DefaultIntEncoder, _ = NewIntEncoder("9ukH1grX75TQS6LzpFAjIivsdZoO0mc8NBwnyYDhtMWEC2V3KaGxfJRPqe4lbU", 62)
var OrderedIntEncoder, _ = NewIntEncoder("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 62)
// EncodeInt 使用默认编码器将整数转换为字节切片
func EncodeInt(u uint64) []byte {
return DefaultIntEncoder.AppendInt(nil, u)
}
// AppendInt 使用默认编码器将整数追加到已有字节切片中
func AppendInt(buf []byte, u uint64) []byte {
return DefaultIntEncoder.AppendInt(buf, u)
}
// DecodeInt 使用默认编码器从字节切片解码为整数
func DecodeInt(buf []byte) uint64 {
return DefaultIntEncoder.DecodeInt(buf)
}
func ExchangeInt(buf []byte) []byte {
return DefaultIntEncoder.ExchangeInt(buf)
}
func HashInt(data []byte, key []byte) []byte {
return DefaultIntEncoder.HashInt(data, key)
}