aboutsummaryrefslogtreecommitdiff
path: root/bencode/bencode.go
blob: 532ac8a6c7c1771e0afd6d0155d0485ab04f2a1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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, ""
}