From: Matt Joiner <anacrolix@gmail.com>
Date: Thu, 28 Oct 2021 05:21:23 +0000 (+1100)
Subject: bencode: Encode arrays of bytes as strings
X-Git-Tag: v1.35.0~12
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=446016cb270c35038387d9447cc4f80f8012ba1d;p=btrtrc.git

bencode: Encode arrays of bytes as strings

This looks appropriate with the use of byte arrays in DHT for BEP44.
---

diff --git a/bencode/encode.go b/bencode/encode.go
index 4c7c8602..3f6c4bb4 100644
--- a/bencode/encode.go
+++ b/bencode/encode.go
@@ -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
diff --git a/bencode/encode_test.go b/bencode/encode_test.go
index 7fc3234a..b0fabc45 100644
--- a/bencode/encode_test.go
+++ b/bencode/encode_test.go
@@ -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:"},