]> Sergey Matveev's repositories - btrtrc.git/blobdiff - bencode/encode.go
Fix addrPortOrZero for unix sockets on Windows
[btrtrc.git] / bencode / encode.go
index 05153a8c273beb5d62a5bc035b31b02fc71a11f3..5e80cb16f5c60cc7c5c720cbd04e49479f3bcd33 100644 (file)
@@ -64,16 +64,18 @@ func (e *Encoder) writeString(s string) {
 }
 
 func (e *Encoder) reflectString(s string) {
-       b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
-       e.write(b)
-       e.writeString(":")
+       e.writeStringPrefix(int64(len(s)))
        e.writeString(s)
 }
 
-func (e *Encoder) reflectByteSlice(s []byte) {
-       b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
+func (e *Encoder) writeStringPrefix(l int64) {
+       b := strconv.AppendInt(e.scratch[:0], l, 10)
        e.write(b)
        e.writeString(":")
+}
+
+func (e *Encoder) reflectByteSlice(s []byte) {
+       e.writeStringPrefix(int64(len(s)))
        e.write(s)
 }
 
@@ -96,10 +98,9 @@ func (e *Encoder) reflectMarshaler(v reflect.Value) bool {
        return true
 }
 
-var bigIntType = reflect.TypeOf(big.Int{})
+var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
 
 func (e *Encoder) reflectValue(v reflect.Value) {
-
        if e.reflectMarshaler(v) {
                return
        }
@@ -161,23 +162,8 @@ func (e *Encoder) reflectValue(v reflect.Value) {
                        e.reflectValue(v.MapIndex(key))
                }
                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
-       case reflect.Array:
-               e.writeString("l")
-               for i, n := 0, v.Len(); i < n; i++ {
-                       e.reflectValue(v.Index(i))
-               }
-               e.writeString("e")
+       case reflect.Slice, reflect.Array:
+               e.reflectSequence(v)
        case reflect.Interface:
                e.reflectValue(v.Elem())
        case reflect.Ptr:
@@ -192,6 +178,37 @@ func (e *Encoder) reflectValue(v reflect.Value) {
        }
 }
 
+func (e *Encoder) reflectSequence(v reflect.Value) {
+       // Use bencode string-type
+       if v.Type().Elem().Kind() == reflect.Uint8 {
+               if v.Kind() != reflect.Slice {
+                       // Can't use []byte optimization
+                       if !v.CanAddr() {
+                               e.writeStringPrefix(int64(v.Len()))
+                               for i := 0; i < v.Len(); i++ {
+                                       var b [1]byte
+                                       b[0] = byte(v.Index(i).Uint())
+                                       e.write(b[:])
+                               }
+                               return
+                       }
+                       v = v.Slice(0, v.Len())
+               }
+               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