bencode: Encode arrays of bytes as strings

This looks appropriate with the use of byte arrays in DHT for BEP44.
This commit is contained in:
Matt Joiner 2021-10-28 16:21:23 +11:00
parent 8b368b3832
commit 446016cb27
2 changed files with 23 additions and 16 deletions

View File

@ -162,22 +162,9 @@ func (e *Encoder) reflectValue(v reflect.Value) {
}
e.writeString("e")
case reflect.Slice:
if v.Type().Elem().Kind() == reflect.Uint8 {
s := v.Bytes()
e.reflectByteSlice(s)
break
}
if v.IsNil() {
e.writeString("le")
break
}
fallthrough
e.reflectSlice(v)
case reflect.Array:
e.writeString("l")
for i, n := 0, v.Len(); i < n; i++ {
e.reflectValue(v.Index(i))
}
e.writeString("e")
e.reflectSlice(v.Slice(0, v.Len()))
case reflect.Interface:
e.reflectValue(v.Elem())
case reflect.Ptr:
@ -192,6 +179,26 @@ func (e *Encoder) reflectValue(v reflect.Value) {
}
}
func (e *Encoder) reflectSlice(v reflect.Value) {
if v.Type().Elem().Kind() == reflect.Uint8 {
// This can panic if v is not addressable, such as by passing an array of bytes by value. We
// could copy them and make a slice to the copy, or the user could just avoid doing this. It
// remains to be seen.
s := v.Bytes()
e.reflectByteSlice(s)
return
}
if v.IsNil() {
e.writeString("le")
return
}
e.writeString("l")
for i, n := 0, v.Len(); i < n; i++ {
e.reflectValue(v.Index(i))
}
e.writeString("e")
}
type encodeField struct {
i func(v reflect.Value) reflect.Value
tag string

View File

@ -50,7 +50,7 @@ var random_encode_tests = []random_encode_test{
{random_struct{123, "nono", "hello"}, "d3:CDE5:hello3:abci123ee"},
{map[string]string{"a": "b", "c": "d"}, "d1:a1:b1:c1:de"},
{[]byte{1, 2, 3, 4}, "4:\x01\x02\x03\x04"},
{[4]byte{1, 2, 3, 4}, "li1ei2ei3ei4ee"},
{&[4]byte{1, 2, 3, 4}, "4:\x01\x02\x03\x04"},
{nil, ""},
{[]byte{}, "0:"},
{[]byte(nil), "0:"},