Update bencode for weekly.2011-12-06

This commit is contained in:
Yves Junqueira 2011-12-17 17:35:20 +01:00
parent e65ed38f87
commit 5c02c4aa77
4 changed files with 173 additions and 176 deletions

View file

@ -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())
}
}
}

View file

@ -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
}

View file

@ -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
View file

@ -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))
}