go-bt/bencode/struct.go

547 lines
12 KiB
Go
Raw Normal View History

2010-01-06 15:38:33 +00:00
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Marshalling and unmarshalling of
// bit torrent bencode data into Go structs using reflection.
//
// Based upon the standard Go language JSON package.
package bencode
import (
"bytes"
2011-12-17 16:35:20 +00:00
"errors"
2010-01-06 15:38:33 +00:00
"fmt"
"io"
2011-12-17 16:35:20 +00:00
2010-01-06 15:38:33 +00:00
"reflect"
"sort"
"strings"
)
type structBuilder struct {
val reflect.Value
// if map_ != nil, write val to map_[key] on each change
2011-12-17 16:35:20 +00:00
map_ reflect.Value
2010-01-06 15:38:33 +00:00
key reflect.Value
}
var nobuilder *structBuilder
func isfloat(v reflect.Value) bool {
2011-12-17 16:35:20 +00:00
switch v.Kind() {
case reflect.Float32, reflect.Float64:
2010-01-06 15:38:33 +00:00
return true
}
return false
}
func setfloat(v reflect.Value, f float64) {
2011-12-17 16:35:20 +00:00
switch v.Kind() {
case reflect.Float32, reflect.Float64:
v.SetFloat(f)
2010-01-06 15:38:33 +00:00
}
}
func setint(val reflect.Value, i int64) {
2011-12-17 16:35:20 +00:00
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))
default:
panic("setint called for bogus type: " + val.Kind().String())
2010-01-06 15:38:33 +00:00
}
}
// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func (b *structBuilder) Flush() {
if b == nil {
return
}
2011-12-17 16:35:20 +00:00
if b.map_.IsValid() {
b.map_.SetMapIndex(b.key, b.val)
2010-01-06 15:38:33 +00:00
}
}
func (b *structBuilder) Int64(i int64) {
if b == nil {
return
}
if !b.val.CanSet() {
x := 0
b.val = reflect.ValueOf(&x).Elem()
}
2010-01-06 15:38:33 +00:00
v := b.val
if isfloat(v) {
setfloat(v, float64(i))
} else {
setint(v, i)
}
}
func (b *structBuilder) Uint64(i uint64) {
if b == nil {
return
}
if !b.val.CanSet() {
x := uint64(0)
b.val = reflect.ValueOf(&x).Elem()
}
2010-01-06 15:38:33 +00:00
v := b.val
if isfloat(v) {
setfloat(v, float64(i))
} else {
setint(v, int64(i))
}
}
func (b *structBuilder) Float64(f float64) {
if b == nil {
return
}
if !b.val.CanSet() {
x := float64(0)
b.val = reflect.ValueOf(&x).Elem()
}
2010-01-06 15:38:33 +00:00
v := b.val
if isfloat(v) {
setfloat(v, f)
} else {
setint(v, int64(f))
}
}
func (b *structBuilder) String(s string) {
if b == nil {
return
}
switch b.val.Kind() {
2011-12-17 16:35:20 +00:00
case reflect.String:
if !b.val.CanSet() {
x := ""
b.val = reflect.ValueOf(&x).Elem()
}
b.val.SetString(s)
2011-12-17 16:35:20 +00:00
case reflect.Interface:
b.val.Set(reflect.ValueOf(s))
2010-01-06 15:38:33 +00:00
}
}
func (b *structBuilder) Array() {
if b == nil {
return
}
2011-12-17 16:35:20 +00:00
if v := b.val; v.Kind() == reflect.Slice {
2010-01-06 15:38:33 +00:00
if v.IsNil() {
2011-12-17 16:35:20 +00:00
v.Set(reflect.MakeSlice(v.Type(), 0, 8))
2010-01-06 15:38:33 +00:00
}
}
}
func (b *structBuilder) Elem(i int) builder {
2010-01-06 15:38:33 +00:00
if b == nil || i < 0 {
return nobuilder
}
2011-12-17 16:35:20 +00:00
switch v := b.val; v.Kind() {
case reflect.Array:
2010-01-06 15:38:33 +00:00
if i < v.Len() {
2011-12-17 16:35:20 +00:00
return &structBuilder{val: v.Index(i)}
2010-01-06 15:38:33 +00:00
}
2011-12-17 16:35:20 +00:00
case reflect.Slice:
2010-01-06 15:38:33 +00:00
if i >= v.Cap() {
n := v.Cap()
if n < 8 {
n = 8
}
for n <= i {
n *= 2
}
2011-12-17 16:35:20 +00:00
nv := reflect.MakeSlice(v.Type(), v.Len(), n)
reflect.Copy(nv, v)
2010-01-06 15:38:33 +00:00
v.Set(nv)
}
if v.Len() <= i && i < v.Cap() {
v.SetLen(i + 1)
}
if i < v.Len() {
2011-12-17 16:35:20 +00:00
return &structBuilder{val: v.Index(i)}
2010-01-06 15:38:33 +00:00
}
}
return nobuilder
}
func (b *structBuilder) Map() {
if b == nil {
return
}
if v := b.val; v.Kind() == reflect.Ptr {
2010-01-06 15:38:33 +00:00
if v.IsNil() {
2011-12-17 16:35:20 +00:00
v.Set(reflect.Zero(v.Type().Elem()).Addr())
2010-01-06 15:38:33 +00:00
b.Flush()
}
2011-12-17 16:35:20 +00:00
b.map_ = reflect.Value{}
2010-01-06 15:38:33 +00:00
b.val = v.Elem()
}
2011-12-17 16:35:20 +00:00
if v := b.val; v.Kind() == reflect.Map && v.IsNil() {
v.Set(reflect.MakeMap(v.Type()))
2010-01-06 15:38:33 +00:00
}
}
func (b *structBuilder) Key(k string) builder {
2010-01-06 15:38:33 +00:00
if b == nil {
return nobuilder
}
2011-12-17 16:35:20 +00:00
switch v := reflect.Indirect(b.val); v.Kind() {
case reflect.Struct:
t := v.Type()
2010-01-06 15:38:33 +00:00
// Case-insensitive field lookup.
k = strings.ToLower(k)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
key := bencodeKey(field)
if strings.ToLower(key) == k ||
2010-01-06 15:38:33 +00:00
strings.ToLower(field.Name) == k {
return &structBuilder{val: v.Field(i)}
}
}
2011-12-17 16:35:20 +00:00
case reflect.Map:
t := v.Type()
if t.Key() != reflect.TypeOf(k) {
2010-01-06 15:38:33 +00:00
break
}
2011-12-17 16:35:20 +00:00
key := reflect.ValueOf(k)
elem := v.MapIndex(key)
if !elem.IsValid() {
v.SetMapIndex(key, reflect.Zero(t.Elem()))
elem = v.MapIndex(key)
2010-01-06 15:38:33 +00:00
}
return &structBuilder{val: elem, map_: v, key: key}
}
return nobuilder
}
// Unmarshal reads and parses the bencode syntax data from data []byte and fills in
2010-01-06 15:38:33 +00:00
// an arbitrary struct or slice pointed at by val.
// It uses the reflect package to assign to fields
// and arrays embedded in val. Well-formed data that does not fit
// into the struct is discarded.
//
// For example, given these definitions:
//
// type Email struct {
// Where string;
// Addr string;
// }
//
// type Result struct {
// Name string;
// Phone string;
// Email []Email
// }
//
// var r = Result{ "name", "phone", nil }
//
// unmarshalling the bencode syntax string
//
// "d5:emailld5:where4:home4:addr15:gre@example.come\
2010-01-06 15:38:33 +00:00
// d5:where4:work4:addr12:gre@work.comee4:name14:Gr\
// ace R. Emlin7:address15:123 Main Streete"
2010-01-06 15:38:33 +00:00
//
// via Unmarshal(s, &r) is equivalent to assigning
//
// r = Result{
// "Grace R. Emlin", // name
// "phone", // no phone given
// []Email{
// Email{ "home", "gre@example.com" },
// Email{ "work", "gre@work.com" }
// }
// }
//
// Note that the field r.Phone has not been modified and
// that the bencode field "address" was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields. Unmarshal uses a case-insensitive
// comparison to match bencode field names to struct field names.
//
// If you provide a tag string for a struct member, the tag string
// will be used as the bencode dictionary key for that member.
// Bencode undestands both the original single-string and updated
// list-of-key-value-pairs tag string syntax. The list-of-key-value
// pairs syntax is assumed, with a fallback to the original single-string
// syntax. The key for bencode values is bencode.
2010-01-06 15:38:33 +00:00
//
// To unmarshal a top-level bencode array, pass in a pointer to an empty
// slice of the correct type.
//
func Unmarshal(data []byte, val interface{}) (err error) {
// matching other encoders, like encoding/json ...
// func Unmarshal(data []byte, v interface{}) error
2010-01-20 04:53:53 +00:00
// If e represents a value, the answer won't get back to the
// caller. Make sure it's a pointer.
2011-12-17 16:35:20 +00:00
if reflect.TypeOf(val).Kind() != reflect.Ptr {
err = errors.New("Attempt to unmarshal into a non-pointer")
2010-01-20 04:53:53 +00:00
return
}
r := bytes.NewReader(data)
err = unmarshalValue(r, reflect.Indirect(reflect.ValueOf(val)))
2010-01-06 15:38:33 +00:00
return
}
func unmarshalValue(r io.Reader, v reflect.Value) (err error) {
2010-01-06 15:38:33 +00:00
var b *structBuilder
// XXX: Decide if the extra codnitions are needed. Affect map?
2011-12-17 16:35:20 +00:00
if ptr := v; ptr.Kind() == reflect.Ptr {
if slice := ptr.Elem(); slice.Kind() == reflect.Slice || slice.Kind() == reflect.Int || slice.Kind() == reflect.String {
2010-01-06 15:38:33 +00:00
b = &structBuilder{val: slice}
}
}
if b == nil {
b = &structBuilder{val: v}
}
err = parse(r, b)
2010-01-06 15:38:33 +00:00
return
}
type MarshalError struct {
T reflect.Type
}
2011-12-17 16:35:20 +00:00
func (e *MarshalError) Error() string {
2010-01-06 15:38:33 +00:00
return "bencode cannot encode value of type " + e.T.String()
}
2011-12-17 16:35:20 +00:00
func writeArrayOrSlice(w io.Writer, val reflect.Value) (err error) {
2010-01-06 15:38:33 +00:00
_, err = fmt.Fprint(w, "l")
if err != nil {
return
}
for i := 0; i < val.Len(); i++ {
2011-12-17 16:35:20 +00:00
if err := writeValue(w, val.Index(i)); err != nil {
2010-01-06 15:38:33 +00:00
return err
}
}
_, err = fmt.Fprint(w, "e")
if err != nil {
return
}
return nil
}
type stringValue struct {
2010-01-06 15:38:33 +00:00
key string
value reflect.Value
}
type stringValueArray []stringValue
2010-01-06 15:38:33 +00:00
// Satisfy sort.Interface
func (a stringValueArray) Len() int { return len(a) }
2010-01-06 15:38:33 +00:00
func (a stringValueArray) Less(i, j int) bool { return a[i].key < a[j].key }
2010-01-06 15:38:33 +00:00
func (a stringValueArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
2010-01-06 15:38:33 +00:00
func writeSVList(w io.Writer, svList stringValueArray) (err error) {
2010-01-06 15:38:33 +00:00
sort.Sort(svList)
2010-07-10 23:06:14 +00:00
for _, sv := range svList {
2010-01-21 06:39:57 +00:00
if isValueNil(sv.value) {
continue // Skip null values
}
2010-01-06 15:38:33 +00:00
s := sv.key
_, err = fmt.Fprintf(w, "%d:%s", len(s), s)
if err != nil {
return
}
if err = writeValue(w, sv.value); err != nil {
return
}
}
return
}
2011-12-17 16:35:20 +00:00
func writeMap(w io.Writer, val reflect.Value) (err error) {
key := val.Type().Key()
if key.Kind() != reflect.String {
2010-01-06 15:38:33 +00:00
return &MarshalError{val.Type()}
}
_, err = fmt.Fprint(w, "d")
if err != nil {
return
}
2011-12-17 16:35:20 +00:00
keys := val.MapKeys()
2010-01-06 15:38:33 +00:00
// Sort keys
svList := make(stringValueArray, len(keys))
2010-07-10 23:06:14 +00:00
for i, key := range keys {
2011-12-17 16:35:20 +00:00
svList[i].key = key.String()
svList[i].value = val.MapIndex(key)
2010-01-06 15:38:33 +00:00
}
err = writeSVList(w, svList)
if err != nil {
return
}
_, err = fmt.Fprint(w, "e")
if err != nil {
return
}
return
}
func bencodeKey(field reflect.StructField) (key string) {
key = field.Name
tag := field.Tag
if len(tag) > 0 {
// Backwards compatability
// If there's a bencode key/value entry in the tag, use it.
key = tag.Get("bencode")
if len(key) == 0 {
// If there is no ":" in the tag, assume it is an old-style tag.
stringTag := string(tag)
if !strings.Contains(stringTag, ":") {
key = stringTag
}
}
}
return
}
2011-12-17 16:35:20 +00:00
func writeStruct(w io.Writer, val reflect.Value) (err error) {
2010-01-06 15:38:33 +00:00
_, err = fmt.Fprint(w, "d")
if err != nil {
return
}
2011-12-17 16:35:20 +00:00
typ := val.Type()
2010-01-06 15:38:33 +00:00
numFields := val.NumField()
svList := make(stringValueArray, numFields)
2010-01-06 15:38:33 +00:00
for i := 0; i < numFields; i++ {
field := typ.Field(i)
svList[i].key = bencodeKey(field)
2010-01-06 15:38:33 +00:00
svList[i].value = val.Field(i)
}
err = writeSVList(w, svList)
if err != nil {
return
}
_, err = fmt.Fprint(w, "e")
if err != nil {
return
}
return
}
2011-12-17 16:35:20 +00:00
func writeValue(w io.Writer, val reflect.Value) (err error) {
if !val.IsValid() {
err = errors.New("Can't write null value")
2010-01-06 15:38:33 +00:00
return
}
2011-12-17 16:35:20 +00:00
switch v := val; v.Kind() {
case reflect.String:
s := v.String()
2010-01-06 15:38:33 +00:00
_, err = fmt.Fprintf(w, "%d:%s", len(s), s)
2011-12-17 16:35:20 +00:00
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:
2010-01-06 15:38:33 +00:00
err = writeArrayOrSlice(w, v)
2011-12-17 16:35:20 +00:00
case reflect.Slice:
2010-01-06 15:38:33 +00:00
err = writeArrayOrSlice(w, v)
2011-12-17 16:35:20 +00:00
case reflect.Map:
2010-01-06 15:38:33 +00:00
err = writeMap(w, v)
2011-12-17 16:35:20 +00:00
case reflect.Struct:
2010-01-06 15:38:33 +00:00
err = writeStruct(w, v)
2011-12-17 16:35:20 +00:00
case reflect.Interface:
2010-01-06 15:38:33 +00:00
err = writeValue(w, v.Elem())
default:
err = &MarshalError{val.Type()}
}
return
}
2010-01-20 15:20:25 +00:00
func isValueNil(val reflect.Value) bool {
2011-12-17 16:35:20 +00:00
if !val.IsValid() {
2010-01-21 06:39:57 +00:00
return true
}
2011-12-17 16:35:20 +00:00
switch v := val; v.Kind() {
case reflect.Interface:
2010-01-20 15:20:25 +00:00
return isValueNil(v.Elem())
default:
2010-01-21 06:39:57 +00:00
return false
2010-01-20 15:20:25 +00:00
}
return false
}
// Marshal writes the bencode encoding of val to w.
//
// Marshal traverses the value v recursively.
//
// Marshal uses the following type-dependent encodings:
//
// Floating point, integer, and Number values encode as bencode numbers.
//
// String values encode as bencode strings.
//
// Array and slice values encode as bencode arrays.
//
// Struct values encode as bencode maps. Each exported struct field
// becomes a member of the object.
// The object's default key string is the struct field name
// but can be specified in the struct field's tag value. The text of
// the struct field's tag value is the key name. Examples:
//
// // Field appears in bencode as key "Field".
// Field int
//
// // Field appears in bencode as key "myName".
// Field int `bencode:"myName"`
//
// Anonymous struct fields are ignored.
//
// Map values encode as bencode objects.
// The map's key type must be string; the object keys are used directly
// as map keys.
//
// Boolean, Pointer, Interface, Channel, complex, and function values cannot
// be encoded in bencode.
// Attempting to encode such a value causes Marshal to return
// a MarshalError.
//
// Bencode cannot represent cyclic data structures and Marshal does not
// handle them. Passing cyclic structures to Marshal will result in
// an infinite recursion.
//
func Marshal(val interface{}) ([]byte, error) {
// matching other encoders, like encoding/json ...
buf := bytes.Buffer{}
err := writeValue(&buf, reflect.ValueOf(val))
return buf.Bytes(), err
2010-01-06 15:38:33 +00:00
}