Update bencode for weekly.2011-12-06
This commit is contained in:
parent
e65ed38f87
commit
5c02c4aa77
4 changed files with 173 additions and 176 deletions
108
bencode_test.go
108
bencode_test.go
|
@ -2,35 +2,35 @@ package bencode
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type any interface{}
|
||||
|
||||
func checkMarshal(expected string, data any) (err os.Error) {
|
||||
func checkMarshal(expected string, data any) (err error) {
|
||||
var b bytes.Buffer
|
||||
if err = Marshal(&b, data); err != nil {
|
||||
return
|
||||
}
|
||||
s := b.String()
|
||||
if expected != s {
|
||||
err = os.NewError(fmt.Sprintf("Expected %s got %s", expected, s))
|
||||
err = errors.New(fmt.Sprintf("Expected %s got %s", expected, s))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func check(expected string, data any) (err os.Error) {
|
||||
func check(expected string, data any) (err error) {
|
||||
if err = checkMarshal(expected, data); err != nil {
|
||||
return
|
||||
}
|
||||
b2 := bytes.NewBufferString(expected)
|
||||
val, err := Decode(b2)
|
||||
if err != nil {
|
||||
err = os.NewError(fmt.Sprint("Failed decoding ", expected, " ", err))
|
||||
err = errors.New(fmt.Sprint("Failed decoding ", expected, " ", err))
|
||||
return
|
||||
}
|
||||
if err = checkFuzzyEqual(data, val); err != nil {
|
||||
|
@ -39,41 +39,41 @@ func check(expected string, data any) (err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
func checkFuzzyEqual(a any, b any) (err os.Error) {
|
||||
func checkFuzzyEqual(a any, b any) (err error) {
|
||||
if !fuzzyEqual(a, b) {
|
||||
err = os.NewError(fmt.Sprint(a, " != ", b,
|
||||
":", reflect.NewValue(a), "!=", reflect.NewValue(b)))
|
||||
err = errors.New(fmt.Sprint(a, " != ", b,
|
||||
":", reflect.ValueOf(a), "!=", reflect.ValueOf(b)))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fuzzyEqual(a, b any) bool {
|
||||
return fuzzyEqualValue(reflect.NewValue(a), reflect.NewValue(b))
|
||||
return fuzzyEqualValue(reflect.ValueOf(a), reflect.ValueOf(b))
|
||||
}
|
||||
|
||||
func checkFuzzyEqualValue(a, b reflect.Value) (err os.Error) {
|
||||
func checkFuzzyEqualValue(a, b reflect.Value) (err error) {
|
||||
if !fuzzyEqualValue(a, b) {
|
||||
err = os.NewError(fmt.Sprint(a, " != ", b,
|
||||
err = errors.New(fmt.Sprint(a, " != ", b,
|
||||
":", a.Interface(), "!=", b.Interface()))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fuzzyEqualInt64(a int64, b reflect.Value) bool {
|
||||
switch vb := b.(type) {
|
||||
case *reflect.IntValue:
|
||||
return a == (vb.Get())
|
||||
switch vb := b; vb.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return a == (vb.Int())
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func fuzzyEqualArrayOrSlice(va reflect.ArrayOrSliceValue, b reflect.Value) bool {
|
||||
switch vb := b.(type) {
|
||||
case *reflect.ArrayValue:
|
||||
func fuzzyEqualArrayOrSlice(va reflect.Value, b reflect.Value) bool {
|
||||
switch vb := b; vb.Kind() {
|
||||
case reflect.Array:
|
||||
return fuzzyEqualArrayOrSlice2(va, vb)
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
return fuzzyEqualArrayOrSlice2(va, vb)
|
||||
default:
|
||||
return false
|
||||
|
@ -82,21 +82,21 @@ func fuzzyEqualArrayOrSlice(va reflect.ArrayOrSliceValue, b reflect.Value) bool
|
|||
}
|
||||
|
||||
func deInterface(a reflect.Value) reflect.Value {
|
||||
switch va := a.(type) {
|
||||
case *reflect.InterfaceValue:
|
||||
switch va := a; va.Kind() {
|
||||
case reflect.Interface:
|
||||
return va.Elem()
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func fuzzyEqualArrayOrSlice2(a reflect.ArrayOrSliceValue, b reflect.ArrayOrSliceValue) bool {
|
||||
func fuzzyEqualArrayOrSlice2(a reflect.Value, b reflect.Value) bool {
|
||||
if a.Len() != b.Len() {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < a.Len(); i++ {
|
||||
ea := deInterface(a.Elem(i))
|
||||
eb := deInterface(b.Elem(i))
|
||||
ea := deInterface(a.Index(i))
|
||||
eb := deInterface(b.Index(i))
|
||||
if !fuzzyEqualValue(ea, eb) {
|
||||
return false
|
||||
}
|
||||
|
@ -104,31 +104,31 @@ func fuzzyEqualArrayOrSlice2(a reflect.ArrayOrSliceValue, b reflect.ArrayOrSlice
|
|||
return true
|
||||
}
|
||||
|
||||
func fuzzyEqualMap(a *reflect.MapValue, b *reflect.MapValue) bool {
|
||||
key := a.Type().(*reflect.MapType).Key()
|
||||
if _, ok := key.(*reflect.StringType); !ok {
|
||||
func fuzzyEqualMap(a reflect.Value, b reflect.Value) bool {
|
||||
key := a.Type().Key()
|
||||
if key.Kind() != reflect.String {
|
||||
return false
|
||||
}
|
||||
key = b.Type().(*reflect.MapType).Key()
|
||||
if _, ok := key.(*reflect.StringType); !ok {
|
||||
key = b.Type().Key()
|
||||
if key.Kind() != reflect.String {
|
||||
return false
|
||||
}
|
||||
|
||||
aKeys, bKeys := a.Keys(), b.Keys()
|
||||
aKeys, bKeys := a.MapKeys(), b.MapKeys()
|
||||
|
||||
if len(aKeys) != len(bKeys) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, k := range aKeys {
|
||||
if !fuzzyEqualValue(a.Elem(k), b.Elem(k)) {
|
||||
if !fuzzyEqualValue(a.MapIndex(k), b.MapIndex(k)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func fuzzyEqualStruct(a *reflect.StructValue, b *reflect.StructValue) bool {
|
||||
func fuzzyEqualStruct(a reflect.Value, b reflect.Value) bool {
|
||||
numA, numB := a.NumField(), b.NumField()
|
||||
if numA != numB {
|
||||
return false
|
||||
|
@ -143,37 +143,37 @@ func fuzzyEqualStruct(a *reflect.StructValue, b *reflect.StructValue) bool {
|
|||
}
|
||||
|
||||
func fuzzyEqualValue(a, b reflect.Value) bool {
|
||||
switch va := a.(type) {
|
||||
case *reflect.StringValue:
|
||||
switch vb := b.(type) {
|
||||
case *reflect.StringValue:
|
||||
return va.Get() == vb.Get()
|
||||
switch va := a; va.Kind() {
|
||||
case reflect.String:
|
||||
switch vb := b; vb.Kind() {
|
||||
case reflect.String:
|
||||
return va.String() == vb.String()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case *reflect.IntValue:
|
||||
return fuzzyEqualInt64(va.Get(), b)
|
||||
case *reflect.ArrayValue:
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return fuzzyEqualInt64(va.Int(), b)
|
||||
case reflect.Array:
|
||||
return fuzzyEqualArrayOrSlice(va, b)
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
return fuzzyEqualArrayOrSlice(va, b)
|
||||
case *reflect.MapValue:
|
||||
switch vb := b.(type) {
|
||||
case *reflect.MapValue:
|
||||
case reflect.Map:
|
||||
switch vb := b; vb.Kind() {
|
||||
case reflect.Map:
|
||||
return fuzzyEqualMap(va, vb)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case *reflect.StructValue:
|
||||
switch vb := b.(type) {
|
||||
case *reflect.StructValue:
|
||||
case reflect.Struct:
|
||||
switch vb := b; vb.Kind() {
|
||||
case reflect.Struct:
|
||||
return fuzzyEqualStruct(va, vb)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case *reflect.InterfaceValue:
|
||||
switch vb := b.(type) {
|
||||
case *reflect.InterfaceValue:
|
||||
case reflect.Interface:
|
||||
switch vb := b; vb.Kind() {
|
||||
case reflect.Interface:
|
||||
return fuzzyEqualValue(va.Elem(), vb.Elem())
|
||||
default:
|
||||
return false
|
||||
|
@ -184,12 +184,12 @@ func fuzzyEqualValue(a, b reflect.Value) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func checkUnmarshal(expected string, data any) (err os.Error) {
|
||||
func checkUnmarshal(expected string, data any) (err error) {
|
||||
if err = checkMarshal(expected, data); err != nil {
|
||||
return
|
||||
}
|
||||
dataValue := reflect.NewValue(data)
|
||||
newOne := reflect.MakeZero(dataValue.Type())
|
||||
dataValue := reflect.ValueOf(data)
|
||||
newOne := reflect.Zero(dataValue.Type())
|
||||
buf := bytes.NewBufferString(expected)
|
||||
if err = UnmarshalValue(buf, newOne); err != nil {
|
||||
return
|
||||
|
@ -223,7 +223,7 @@ func TestDecode(t *testing.T) {
|
|||
}
|
||||
for _, sv := range tests {
|
||||
if err := check(sv.s, sv.v); err != nil {
|
||||
t.Error(err.String())
|
||||
t.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ func TestUnmarshal(t *testing.T) {
|
|||
}
|
||||
for _, sv := range tests {
|
||||
if err := checkUnmarshal(sv.s, sv.v); err != nil {
|
||||
t.Error(err.String())
|
||||
t.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
33
decode.go
33
decode.go
|
@ -3,14 +3,12 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Represents bencode data structure using native Go types: booleans, floats,
|
||||
// strings, arrays, and maps.
|
||||
// strings, slices, and maps.
|
||||
|
||||
package bencode
|
||||
|
||||
import (
|
||||
"container/vector"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Decode a bencode stream
|
||||
|
@ -18,12 +16,12 @@ import (
|
|||
// Decode parses the stream r and returns the
|
||||
// generic bencode object representation. The object representation is a tree
|
||||
// of Go data types. The data return value may be one of string,
|
||||
// int64, uint64, []interface{} or map[string]interface{}. The array and map
|
||||
// int64, uint64, []interface{} or map[string]interface{}. The slice and map
|
||||
// elements may in turn contain any of the types listed above and so on.
|
||||
//
|
||||
// If Decode encounters a syntax error, it returns with err set to an
|
||||
// instance of ParseError. See ParseError documentation for details.
|
||||
func Decode(r io.Reader) (data interface{}, err os.Error) {
|
||||
func Decode(r io.Reader) (data interface{}, err error) {
|
||||
jb := newDecoder(nil, nil)
|
||||
err = Parse(r, jb)
|
||||
if err == nil {
|
||||
|
@ -35,7 +33,7 @@ func Decode(r io.Reader) (data interface{}, err os.Error) {
|
|||
type decoder struct {
|
||||
// A value being constructed.
|
||||
value interface{}
|
||||
// Container entity to flush into. Can be either vector.Vector or
|
||||
// Container entity to flush into. Can be either []interface{} or
|
||||
// map[string]interface{}.
|
||||
container interface{}
|
||||
// The index into the container interface. Either int or string.
|
||||
|
@ -58,19 +56,24 @@ func (j *decoder) Bool(b bool) { j.value = b }
|
|||
|
||||
func (j *decoder) Null() { j.value = nil }
|
||||
|
||||
func (j *decoder) Array() { j.value = new(vector.Vector) }
|
||||
func (j *decoder) Array() { j.value = make([]interface{}, 0, 8) }
|
||||
|
||||
func (j *decoder) Map() { j.value = make(map[string]interface{}) }
|
||||
|
||||
func (j *decoder) Elem(i int) Builder {
|
||||
v, ok := j.value.(*vector.Vector)
|
||||
v, ok := j.value.([]interface{})
|
||||
if !ok {
|
||||
v = new(vector.Vector)
|
||||
v = make([]interface{}, 0, 8)
|
||||
j.value = v
|
||||
}
|
||||
if v.Len() <= i {
|
||||
v.Resize(i+1, (i+1)*2)
|
||||
lens := len(v)
|
||||
if cap(v) <= lens {
|
||||
news := make([]interface{}, 0, lens*2)
|
||||
copy(news, j.value.([]interface{}))
|
||||
v = news
|
||||
}
|
||||
v = v[0 : lens+1]
|
||||
j.value = v
|
||||
return newDecoder(v, i)
|
||||
}
|
||||
|
||||
|
@ -85,9 +88,9 @@ func (j *decoder) Key(s string) Builder {
|
|||
|
||||
func (j *decoder) Flush() {
|
||||
switch c := j.container.(type) {
|
||||
case *vector.Vector:
|
||||
case []interface{}:
|
||||
index := j.index.(int)
|
||||
c.Set(index, j.Copy())
|
||||
c[index] = j.Copy()
|
||||
case map[string]interface{}:
|
||||
index := j.index.(string)
|
||||
c[index] = j.Copy()
|
||||
|
@ -96,9 +99,5 @@ func (j *decoder) Flush() {
|
|||
|
||||
// Get the value built by this builder.
|
||||
func (j *decoder) Copy() interface{} {
|
||||
switch v := j.value.(type) {
|
||||
case *vector.Vector:
|
||||
return v.Copy()
|
||||
}
|
||||
return j.value
|
||||
}
|
||||
|
|
34
parse.go
34
parse.go
|
@ -9,16 +9,16 @@ package bencode
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Reader interface {
|
||||
io.Reader
|
||||
ReadByte() (c byte, err os.Error)
|
||||
UnreadByte() os.Error
|
||||
ReadByte() (c byte, err error)
|
||||
UnreadByte() error
|
||||
}
|
||||
|
||||
// Parser
|
||||
|
@ -29,7 +29,7 @@ type Reader interface {
|
|||
// Calling a method like Int64(i) sets that object to i.
|
||||
// Calling a method like Elem(i) or Key(s) creates a
|
||||
// new builder for a subpiece of the object (logically,
|
||||
// an array element or a map key).
|
||||
// a slice element or a map key).
|
||||
//
|
||||
// There are two Builders, in other files.
|
||||
// The decoder builds a generic bencode structures
|
||||
|
@ -38,7 +38,6 @@ type Reader interface {
|
|||
// nested data structure, using the "map keys"
|
||||
// as struct field names.
|
||||
|
||||
|
||||
// A Builder is an interface implemented by clients and passed
|
||||
// to the bencode parser. It gives clients full control over the
|
||||
// eventual representation returned by the parser.
|
||||
|
@ -58,7 +57,7 @@ type Builder interface {
|
|||
Flush()
|
||||
}
|
||||
|
||||
func collectInt(r Reader, delim byte) (buf []byte, err os.Error) {
|
||||
func collectInt(r Reader, delim byte) (buf []byte, err error) {
|
||||
for {
|
||||
var c byte
|
||||
c, err = r.ReadByte()
|
||||
|
@ -69,7 +68,7 @@ func collectInt(r Reader, delim byte) (buf []byte, err os.Error) {
|
|||
return
|
||||
}
|
||||
if !(c == '-' || (c >= '0' && c <= '9')) {
|
||||
err = os.NewError("expected digit")
|
||||
err = errors.New("expected digit")
|
||||
return
|
||||
}
|
||||
buf = append(buf, c)
|
||||
|
@ -77,22 +76,22 @@ func collectInt(r Reader, delim byte) (buf []byte, err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
func decodeInt64(r Reader, delim byte) (data int64, err os.Error) {
|
||||
func decodeInt64(r Reader, delim byte) (data int64, err error) {
|
||||
buf, err := collectInt(r, delim)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
data, err = strconv.Atoi64(string(buf))
|
||||
data, err = strconv.ParseInt(string(buf), 10, 64)
|
||||
return
|
||||
}
|
||||
|
||||
func decodeString(r Reader) (data string, err os.Error) {
|
||||
func decodeString(r Reader) (data string, err error) {
|
||||
length, err := decodeInt64(r, ':')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if length < 0 {
|
||||
err = os.NewError("Bad string length")
|
||||
err = errors.New("Bad string length")
|
||||
return
|
||||
}
|
||||
var buf = make([]byte, length)
|
||||
|
@ -104,8 +103,7 @@ func decodeString(r Reader) (data string, err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
func parse(r Reader, build Builder) (err os.Error) {
|
||||
Switch:
|
||||
func parse(r Reader, build Builder) (err error) {
|
||||
c, err := r.ReadByte()
|
||||
if err != nil {
|
||||
goto exit
|
||||
|
@ -163,12 +161,12 @@ Switch:
|
|||
var i2 uint64
|
||||
str = string(buf)
|
||||
// If the number is exactly an integer, use that.
|
||||
if i, err = strconv.Atoi64(str); err == nil {
|
||||
if i, err = strconv.ParseInt(str, 10, 64); err == nil {
|
||||
build.Int64(i)
|
||||
} else if i2, err = strconv.Atoui64(str); err == nil {
|
||||
} else if i2, err = strconv.ParseUint(str, 10, 64); err == nil {
|
||||
build.Uint64(i2)
|
||||
} else {
|
||||
err = os.NewError("Bad integer")
|
||||
err = errors.New("Bad integer")
|
||||
}
|
||||
|
||||
case c == 'l':
|
||||
|
@ -194,7 +192,7 @@ Switch:
|
|||
n++
|
||||
}
|
||||
default:
|
||||
err = os.NewError(fmt.Sprintf("Unexpected character: '%v'", c))
|
||||
err = errors.New(fmt.Sprintf("Unexpected character: '%v'", c))
|
||||
}
|
||||
exit:
|
||||
build.Flush()
|
||||
|
@ -203,7 +201,7 @@ exit:
|
|||
|
||||
// Parse parses the bencode stream and makes calls to
|
||||
// the builder to construct a parsed representation.
|
||||
func Parse(r io.Reader, builder Builder) (err os.Error) {
|
||||
func Parse(r io.Reader, builder Builder) (err error) {
|
||||
rr, ok := r.(Reader)
|
||||
if !ok {
|
||||
rr = bufio.NewReader(r)
|
||||
|
|
174
struct.go
174
struct.go
|
@ -10,9 +10,10 @@
|
|||
package bencode
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -22,35 +23,35 @@ type structBuilder struct {
|
|||
val reflect.Value
|
||||
|
||||
// if map_ != nil, write val to map_[key] on each change
|
||||
map_ *reflect.MapValue
|
||||
map_ reflect.Value
|
||||
key reflect.Value
|
||||
}
|
||||
|
||||
var nobuilder *structBuilder
|
||||
|
||||
func isfloat(v reflect.Value) bool {
|
||||
switch v.(type) {
|
||||
case *reflect.FloatValue:
|
||||
switch v.Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func setfloat(v reflect.Value, f float64) {
|
||||
switch v := v.(type) {
|
||||
case *reflect.FloatValue:
|
||||
v.Set(f)
|
||||
switch v.Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
v.SetFloat(f)
|
||||
}
|
||||
}
|
||||
|
||||
func setint(val reflect.Value, i int64) {
|
||||
switch v := val.(type) {
|
||||
case *reflect.IntValue:
|
||||
v.Set(int64(i))
|
||||
case *reflect.UintValue:
|
||||
v.Set(uint64(i))
|
||||
case *reflect.InterfaceValue:
|
||||
v.Set(reflect.NewValue(i))
|
||||
switch v := val; v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
v.SetInt(int64(i))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
v.SetUint(uint64(i))
|
||||
case reflect.Interface:
|
||||
v.Set(reflect.ValueOf(i))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,8 +61,8 @@ func (b *structBuilder) Flush() {
|
|||
if b == nil {
|
||||
return
|
||||
}
|
||||
if b.map_ != nil {
|
||||
b.map_.SetElem(b.key, b.val)
|
||||
if b.map_.IsValid() {
|
||||
b.map_.SetMapIndex(b.key, b.val)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,11 +107,11 @@ func (b *structBuilder) String(s string) {
|
|||
return
|
||||
}
|
||||
|
||||
switch v := b.val.(type) {
|
||||
case *reflect.StringValue:
|
||||
v.Set(s)
|
||||
case *reflect.InterfaceValue:
|
||||
v.Set(reflect.NewValue(s))
|
||||
switch v := b.val; v.Kind() {
|
||||
case reflect.String:
|
||||
v.SetString(s)
|
||||
case reflect.Interface:
|
||||
v.Set(reflect.ValueOf(s))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,9 +119,9 @@ func (b *structBuilder) Array() {
|
|||
if b == nil {
|
||||
return
|
||||
}
|
||||
if v, ok := b.val.(*reflect.SliceValue); ok {
|
||||
if v := b.val; v.Kind() == reflect.Slice {
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8))
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, 8))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,12 +130,12 @@ func (b *structBuilder) Elem(i int) Builder {
|
|||
if b == nil || i < 0 {
|
||||
return nobuilder
|
||||
}
|
||||
switch v := b.val.(type) {
|
||||
case *reflect.ArrayValue:
|
||||
switch v := b.val; v.Kind() {
|
||||
case reflect.Array:
|
||||
if i < v.Len() {
|
||||
return &structBuilder{val: v.Elem(i)}
|
||||
return &structBuilder{val: v.Index(i)}
|
||||
}
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
if i >= v.Cap() {
|
||||
n := v.Cap()
|
||||
if n < 8 {
|
||||
|
@ -143,7 +144,7 @@ func (b *structBuilder) Elem(i int) Builder {
|
|||
for n <= i {
|
||||
n *= 2
|
||||
}
|
||||
nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n)
|
||||
nv := reflect.MakeSlice(v.Type(), v.Len(), n)
|
||||
reflect.Copy(nv, v)
|
||||
v.Set(nv)
|
||||
}
|
||||
|
@ -151,7 +152,7 @@ func (b *structBuilder) Elem(i int) Builder {
|
|||
v.SetLen(i + 1)
|
||||
}
|
||||
if i < v.Len() {
|
||||
return &structBuilder{val: v.Elem(i)}
|
||||
return &structBuilder{val: v.Index(i)}
|
||||
}
|
||||
}
|
||||
return nobuilder
|
||||
|
@ -161,16 +162,16 @@ func (b *structBuilder) Map() {
|
|||
if b == nil {
|
||||
return
|
||||
}
|
||||
if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
|
||||
if v := b.val; v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
if v.IsNil() {
|
||||
v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
|
||||
v.Set(reflect.Zero(v.Type().Elem()).Addr())
|
||||
b.Flush()
|
||||
}
|
||||
b.map_ = nil
|
||||
b.map_ = reflect.Value{}
|
||||
b.val = v.Elem()
|
||||
}
|
||||
if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
|
||||
v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
|
||||
if v := b.val; v.Kind() == reflect.Map && v.IsNil() {
|
||||
v.Set(reflect.MakeMap(v.Type()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,28 +179,28 @@ func (b *structBuilder) Key(k string) Builder {
|
|||
if b == nil {
|
||||
return nobuilder
|
||||
}
|
||||
switch v := reflect.Indirect(b.val).(type) {
|
||||
case *reflect.StructValue:
|
||||
t := v.Type().(*reflect.StructType)
|
||||
switch v := reflect.Indirect(b.val); v.Kind() {
|
||||
case reflect.Struct:
|
||||
t := v.Type()
|
||||
// Case-insensitive field lookup.
|
||||
k = strings.ToLower(k)
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
if strings.ToLower(field.Tag) == k ||
|
||||
if strings.ToLower(string(field.Tag)) == k ||
|
||||
strings.ToLower(field.Name) == k {
|
||||
return &structBuilder{val: v.Field(i)}
|
||||
}
|
||||
}
|
||||
case *reflect.MapValue:
|
||||
t := v.Type().(*reflect.MapType)
|
||||
if t.Key() != reflect.Typeof(k) {
|
||||
case reflect.Map:
|
||||
t := v.Type()
|
||||
if t.Key() != reflect.TypeOf(k) {
|
||||
break
|
||||
}
|
||||
key := reflect.NewValue(k)
|
||||
elem := v.Elem(key)
|
||||
if elem == nil {
|
||||
v.SetElem(key, reflect.MakeZero(t.Elem()))
|
||||
elem = v.Elem(key)
|
||||
key := reflect.ValueOf(k)
|
||||
elem := v.MapIndex(key)
|
||||
if !elem.IsValid() {
|
||||
v.SetMapIndex(key, reflect.Zero(t.Elem()))
|
||||
elem = v.MapIndex(key)
|
||||
}
|
||||
return &structBuilder{val: elem, map_: v, key: key}
|
||||
}
|
||||
|
@ -258,26 +259,26 @@ func (b *structBuilder) Key(k string) Builder {
|
|||
// slice of the correct type.
|
||||
//
|
||||
|
||||
func Unmarshal(r io.Reader, val interface{}) (err os.Error) {
|
||||
func Unmarshal(r io.Reader, val interface{}) (err error) {
|
||||
// If e represents a value, the answer won't get back to the
|
||||
// caller. Make sure it's a pointer.
|
||||
if _, ok := reflect.Typeof(val).(*reflect.PtrType); !ok {
|
||||
err = os.ErrorString("Attempt to unmarshal into a non-pointer")
|
||||
if reflect.TypeOf(val).Kind() != reflect.Ptr {
|
||||
err = errors.New("Attempt to unmarshal into a non-pointer")
|
||||
return
|
||||
}
|
||||
err = UnmarshalValue(r, reflect.NewValue(val))
|
||||
err = UnmarshalValue(r, reflect.ValueOf(val))
|
||||
return
|
||||
}
|
||||
|
||||
// This API is public primarily to make testing easier, but it is available if you
|
||||
// have a use for it.
|
||||
|
||||
func UnmarshalValue(r io.Reader, v reflect.Value) (err os.Error) {
|
||||
func UnmarshalValue(r io.Reader, v reflect.Value) (err error) {
|
||||
var b *structBuilder
|
||||
|
||||
// If val is a pointer to a slice, we append to the slice.
|
||||
if ptr, ok := v.(*reflect.PtrValue); ok {
|
||||
if slice, ok := ptr.Elem().(*reflect.SliceValue); ok {
|
||||
if ptr := v; ptr.Kind() == reflect.Ptr {
|
||||
if slice := ptr.Elem(); slice.Kind() == reflect.Slice {
|
||||
b = &structBuilder{val: slice}
|
||||
}
|
||||
}
|
||||
|
@ -294,17 +295,17 @@ type MarshalError struct {
|
|||
T reflect.Type
|
||||
}
|
||||
|
||||
func (e *MarshalError) String() string {
|
||||
func (e *MarshalError) Error() string {
|
||||
return "bencode cannot encode value of type " + e.T.String()
|
||||
}
|
||||
|
||||
func writeArrayOrSlice(w io.Writer, val reflect.ArrayOrSliceValue) (err os.Error) {
|
||||
func writeArrayOrSlice(w io.Writer, val reflect.Value) (err error) {
|
||||
_, err = fmt.Fprint(w, "l")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
if err := writeValue(w, val.Elem(i)); err != nil {
|
||||
if err := writeValue(w, val.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +332,7 @@ func (a StringValueArray) Less(i, j int) bool { return a[i].key < a[j].key }
|
|||
|
||||
func (a StringValueArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
func writeSVList(w io.Writer, svList StringValueArray) (err os.Error) {
|
||||
func writeSVList(w io.Writer, svList StringValueArray) (err error) {
|
||||
sort.Sort(svList)
|
||||
|
||||
for _, sv := range svList {
|
||||
|
@ -351,10 +352,9 @@ func writeSVList(w io.Writer, svList StringValueArray) (err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
|
||||
func writeMap(w io.Writer, val *reflect.MapValue) (err os.Error) {
|
||||
key := val.Type().(*reflect.MapType).Key()
|
||||
if _, ok := key.(*reflect.StringType); !ok {
|
||||
func writeMap(w io.Writer, val reflect.Value) (err error) {
|
||||
key := val.Type().Key()
|
||||
if key.Kind() != reflect.String {
|
||||
return &MarshalError{val.Type()}
|
||||
}
|
||||
_, err = fmt.Fprint(w, "d")
|
||||
|
@ -362,14 +362,14 @@ func writeMap(w io.Writer, val *reflect.MapValue) (err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
keys := val.Keys()
|
||||
keys := val.MapKeys()
|
||||
|
||||
// Sort keys
|
||||
|
||||
svList := make(StringValueArray, len(keys))
|
||||
for i, key := range keys {
|
||||
svList[i].key = key.(*reflect.StringValue).Get()
|
||||
svList[i].value = val.Elem(key)
|
||||
svList[i].key = key.String()
|
||||
svList[i].value = val.MapIndex(key)
|
||||
}
|
||||
|
||||
err = writeSVList(w, svList)
|
||||
|
@ -384,13 +384,13 @@ func writeMap(w io.Writer, val *reflect.MapValue) (err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) {
|
||||
func writeStruct(w io.Writer, val reflect.Value) (err error) {
|
||||
_, err = fmt.Fprint(w, "d")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
typ := val.Type().(*reflect.StructType)
|
||||
typ := val.Type()
|
||||
|
||||
numFields := val.NumField()
|
||||
svList := make(StringValueArray, numFields)
|
||||
|
@ -399,7 +399,7 @@ func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) {
|
|||
field := typ.Field(i)
|
||||
key := field.Name
|
||||
if len(field.Tag) > 0 {
|
||||
key = field.Tag
|
||||
key = string(field.Tag)
|
||||
}
|
||||
svList[i].key = key
|
||||
svList[i].value = val.Field(i)
|
||||
|
@ -417,29 +417,29 @@ func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
|
||||
if val == nil {
|
||||
err = os.NewError("Can't write null value")
|
||||
func writeValue(w io.Writer, val reflect.Value) (err error) {
|
||||
if !val.IsValid() {
|
||||
err = errors.New("Can't write null value")
|
||||
return
|
||||
}
|
||||
|
||||
switch v := val.(type) {
|
||||
case *reflect.StringValue:
|
||||
s := v.Get()
|
||||
switch v := val; v.Kind() {
|
||||
case reflect.String:
|
||||
s := v.String()
|
||||
_, err = fmt.Fprintf(w, "%d:%s", len(s), s)
|
||||
case *reflect.IntValue:
|
||||
_, err = fmt.Fprintf(w, "i%de", v.Get())
|
||||
case *reflect.UintValue:
|
||||
_, err = fmt.Fprintf(w, "i%de", v.Get())
|
||||
case *reflect.ArrayValue:
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
_, err = fmt.Fprintf(w, "i%de", v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
_, err = fmt.Fprintf(w, "i%de", v.Uint())
|
||||
case reflect.Array:
|
||||
err = writeArrayOrSlice(w, v)
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
err = writeArrayOrSlice(w, v)
|
||||
case *reflect.MapValue:
|
||||
case reflect.Map:
|
||||
err = writeMap(w, v)
|
||||
case *reflect.StructValue:
|
||||
case reflect.Struct:
|
||||
err = writeStruct(w, v)
|
||||
case *reflect.InterfaceValue:
|
||||
case reflect.Interface:
|
||||
err = writeValue(w, v.Elem())
|
||||
default:
|
||||
err = &MarshalError{val.Type()}
|
||||
|
@ -448,11 +448,11 @@ func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
|
|||
}
|
||||
|
||||
func isValueNil(val reflect.Value) bool {
|
||||
if val == nil {
|
||||
if !val.IsValid() {
|
||||
return true
|
||||
}
|
||||
switch v := val.(type) {
|
||||
case *reflect.InterfaceValue:
|
||||
switch v := val; v.Kind() {
|
||||
case reflect.Interface:
|
||||
return isValueNil(v.Elem())
|
||||
default:
|
||||
return false
|
||||
|
@ -460,6 +460,6 @@ func isValueNil(val reflect.Value) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func Marshal(w io.Writer, val interface{}) os.Error {
|
||||
return writeValue(w, reflect.NewValue(val))
|
||||
func Marshal(w io.Writer, val interface{}) error {
|
||||
return writeValue(w, reflect.ValueOf(val))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue