diff options
Diffstat (limited to 'bencode/encode.go')
| -rw-r--r-- | bencode/encode.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/bencode/encode.go b/bencode/encode.go new file mode 100644 index 0000000..4890359 --- /dev/null +++ b/bencode/encode.go @@ -0,0 +1,92 @@ +package bencode + +import ( + "errors" + "fmt" + "sort" +) + +// Encode encodes a string, int, dict or list value to a bencoded string. +func Encode(data interface{}) ([]byte, error) { + return encodeItem(data) +} + +// EncodeString encodes a string value. +func EncodeString(data string) ([]byte, error) { + length := fmt.Sprintf("%d:", len(data)) + out := make([]byte, 0, len(length)+len(data)+1) + out = append(out, []byte(length)...) + return append(out, []byte(data)...), nil +} + +// EncodeInt encodes a int value. +func EncodeInt(data int64) ([]byte, error) { + ib := fmt.Sprintf("i%de", data) + return []byte(ib), nil +} + +// EncodeDict encodes a dict value. +func EncodeDict(data map[string]interface{}) ([]byte, error) { + out := make([]byte, 0, 2) + out = append(out, 'd') + + // Sort keys + list := make(sort.StringSlice, len(data)) + i := 0 + for key := range data { + list[i] = key + i++ + } + list.Sort() + + for _, key := range list { + keyb, err := EncodeString(key) + if err != nil { + return nil, err + } + value, err := encodeItem(data[key]) + if err != nil { + return nil, err + } + out = append(out, keyb...) + out = append(out, value...) + } + return append(out, 'e'), nil +} + +// EncodeList encodes a list value. +func EncodeList(data []interface{}) ([]byte, error) { + out := make([]byte, 0, 2) + out = append(out, 'l') + + for _, item := range data { + b, err := encodeItem(item) + if err != nil { + return nil, err + } + out = append(out, b...) + } + return append(out, 'e'), nil +} + +// EncodeItem encodes an item of dict or list. +func encodeItem(data interface{}) ([]byte, error) { + switch v := data.(type) { + case string: + return EncodeString(v) + case int: + return EncodeInt(int64(v)) + case int16: + return EncodeInt(int64(v)) + case int32: + return EncodeInt(int64(v)) + case int64: + return EncodeInt(int64(v)) + case []interface{}: + return EncodeList(v) + case map[string]interface{}: + return EncodeDict(v) + default: + return nil, errors.New("bencode: invalid type to encode") + } +} |
