package bencode import ( "bytes" "errors" "fmt" "io" "log" "reflect" "strings" ) // mapping / limitations // dict -> struct // list -> aray of same type type itemType int const ( itemError itemType = iota itemDict itemList itemNumber itemString ) var ErrValue = errors.New("invalid value") func Marshal(v interface{}) ([]byte, error) { var out bytes.Buffer val := reflect.ValueOf(v) err := marshalField(&out, val) return out.Bytes(), err } func marshalField(out io.Writer, v reflect.Value) error { if !v.IsValid() { return ErrValue } log.Println(v.Kind()) switch v.Kind() { case reflect.String: marshalString(out, v.String()) case reflect.Int: marshalInt(out, v.Int()) case reflect.Slice: fmt.Fprint(out, "l") for i := 0; i < v.Len(); i++ { marshalField(out, v.Index(i)) } fmt.Fprint(out, "e") case reflect.Struct: t := v.Type() fmt.Fprint(out, "d") for i := 0; i < t.NumField(); i++ { tag := t.Field(i).Tag.Get("bencode") if tag == "-" { continue } name, _ := parseTag(tag) if name == "" { name = t.Field(i).Name } marshalString(out, name) marshalField(out, v.Field(i)) } fmt.Fprint(out, "e") } return nil } func marshalString(out io.Writer, s string) { fmt.Fprintf(out, "%d:%s", len(s), s) } func marshalInt(out io.Writer, i int64) { fmt.Fprintf(out, "i%de", i) } func Unmarshal(data []byte, v interface{}) error { return nil } func parseTag(tag string) (string, string) { if i := strings.Index(tag, ","); i != -1 { return tag[:i], tag[i+1:] } return tag, "" }