我在Go中有以下自定义编码算法(类似于Base64)
func shuffle(input rune) rune {
switch {
case input > 37:
return input + 59
case input > 11:
return input + 53
case input > 1:
return input + 46
default:
return 50*input + 45
}
}
func customEncode(input []byte) string {
inputLen := len(input)
output := make([]rune, 0, inputLen*4)
for i := 0; i < inputLen; i += 3 {
var chunk uint32
for j := 0; j < 3; j++ {
shift := uint(16 - j*8)
if i+j < inputLen {
chunk |= uint32(input[i+j]) << shift
} else {
chunk |= uint32(0) << shift
}
}
output = append(output,
shuffle(rune((chunk>>18)&63)),
shuffle(rune((chunk>>12)&63)),
shuffle(rune((chunk>>6)&63)),
shuffle(rune((chunk)&63)),
)
}
inputLenMod3 := inputLen % 3
if inputLenMod3 == 1 {
output = output[:len(output)-2]
} else if inputLenMod3 == 2 {
output = output[:len(output)-1]
}
stringOutput := string(output)
return stringOutput
}
我正在尝试为编码器编写一个解码器,这是我迄今为止的尝试:
func unshuffle(input rune) rune {
switch {
case input > 95:
return input - 59
case input > 69:
return input - 53
case input > 49:
return input - 46
default:
return (input + 45) / 50
}
}
func customDecode(encoded string) []byte {
output := make([]byte, 0, len(encoded))
for i := 0; i < len(encoded); i += 4 {
chunk := uint32(0)
for j := 0; j < 4 && i+j < len(encoded); j++ {
chunk |= uint32(unshuffle(rune(encoded[i+j]))) << (18 - j*6)
}
output = append(output,
byte((chunk>>16)&0xFF),
byte((chunk>>8)&0xFF),
byte(chunk&0xFF),
)
}
if len(encoded)%4 == 3 {
output = output[:len(output)-1]
} else if len(encoded)%4 == 2 {
output = output[:len(output)-2]
}
return output
}
这是我的测试代码,用于检查输出的有效性:
func TestEncoding(t *testing.T) {
input := "LoremipsLoremips"
encoded := customEncode([]byte(input))
decoded := customDecode(encoded)
fmt.Println(fmt.Sprintf("Encoded: %s", encoded))
fmt.Println([]byte(input))
fmt.Println(decoded)
if !bytes.Equal([]byte(input), decoded) {
t.Fail()
}
}
//Encoded: H4xmNKpdQ5BAPr7ZPKZkQk
//[76 111 114 101 109 105 112 115 76 111 114 101 109 105 112 115]
//[76 111 114 101 109 105 112 117 19 111 114 101 109 105 112 115]
//--- FAIL: TestEncoding (0.00s)
从测试结果可以看出,输出字节与输入字节略有不同。我不确定我做错了什么 - 但如何修复解码器以确保输出与输入字节匹配?
有趣的是,如果我使用
Lorem
作为输入字符串,解码后的字节是正确的。
我没有花任何精力去理解你的算法;这是基于我在浏览代码时发现的一个问题的快速答案(很可能还有其他问题!)。
看起来
customEncode
将 3 个字节转换为 4 个字节(每个字节的值在 0 到 63 之间 - 这是基于 &63
的),然后将这些值传递给 shuffle
。让我们测试您的 shuffle
函数的这些值:
func main() {
for i := 0; i <= 63; i++ {
processed := unshuffle(shuffle(rune(i)))
if rune(i) != processed {
fmt.Println(i)
}
}
}
这将输出以下内容(playground):
0
1
2
3
12
13
14
15
16
看来你有一个错误。看看你的
shuffle
函数,我注意到超过 11
的值会增加 53
(意味着结果将超过 65
)。然而,在 unshuffle
中,您正在寻找 case input > 69
。如果我们解决这个问题(以及其他比较中的类似问题):
func shuffle(input rune) rune {
switch {
case input > 37:
return input + 59
case input > 11:
return input + 53
case input > 1:
return input + 46
default:
return input + 45
}
}
func unshuffle(input rune) rune {
switch {
case input > 96:
return input - 59
case input > 64:
return input - 53
case input > 47:
return input - 46
default:
return input - 45
}
}
测试有效playground(请注意,我还删除了
* 50
案例中的 default
,因为这看起来是错误的)。通过这些更改,您的测试也通过了(但值得使用随机序列进行测试(例如)。请注意,我不能保证输出正确,因为我只考虑了您确定的单个问题。