From 5c02c4aa775d630e4440f9d09384135f03db822f Mon Sep 17 00:00:00 2001 From: Yves Junqueira Date: Sat, 17 Dec 2011 17:35:20 +0100 Subject: [PATCH] Update bencode for weekly.2011-12-06 --- bencode_test.go | 108 +++++++++++++++--------------- decode.go | 33 +++++---- parse.go | 34 +++++----- struct.go | 174 ++++++++++++++++++++++++------------------------ 4 files changed, 173 insertions(+), 176 deletions(-) diff --git a/bencode_test.go b/bencode_test.go index cbcd5f6..7cc738f 100644 --- a/bencode_test.go +++ b/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()) } } } diff --git a/decode.go b/decode.go index 12b6133..77764b2 100644 --- a/decode.go +++ b/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 } diff --git a/parse.go b/parse.go index 0cb2541..02d46e3 100644 --- a/parse.go +++ b/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) diff --git a/struct.go b/struct.go index cd9b583..4576759 100644 --- a/struct.go +++ b/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)) }