aboutsummaryrefslogtreecommitdiff
path: root/bencode/encode.go
diff options
context:
space:
mode:
Diffstat (limited to 'bencode/encode.go')
-rw-r--r--bencode/encode.go92
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")
+ }
+}