Giter Site home page Giter Site logo

bencode's People

Contributors

abharambe avatar cbodley avatar cenkalti avatar deoxxa avatar garyburd avatar glendc avatar keks avatar liamzebedee avatar lyoshenka avatar pmezard avatar varyoo avatar zeebo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

bencode's Issues

Decode from bytes

I think it would be good to add some sort of helper function in the form:

func NewDecoderFromBytes(data []byte) *Decoder {
    reader := bytes.NewBuffer(data)
    return NewDecoder(reader)
}

I frequently find myself using this and it would assist in shorthand for RawMessage processing.

Add Unmarshaler/Marshaler interface support

Currently it is not possible to control how a type is to be encoded (and decoded again). However similar to other packages (YAML/JSON), it would be quite useful to be able to control this for certain types.

As you seem to take inspiration from the std JSON package I think we can keep the Marshaler as simple as:

// Marshaler is the interface implemented by types
// that can marshal themselves into valid bencode.
type Marshaler interface {
	MarshalBencode() ([]byte, error)
}

I think implementing that could be as simple as:

diff --git a/encode.go b/encode.go
index eac347a..3ca2e40 100644
--- a/encode.go
+++ b/encode.go
@@ -29,6 +29,12 @@ func (p sortFields) Less(i, j int) bool {
 }
 func (p sortFields) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
 
+// Marshaler is the interface implemented by types
+// that can marshal themselves into valid bencode.
+type Marshaler interface {
+	MarshalBencode() ([]byte, error)
+}
+
 //An Encoder writes bencoded objects to an output stream.
 type Encoder struct {
 	w io.Writer
@@ -81,6 +87,18 @@ func encodeValue(w io.Writer, val reflect.Value) error {
 		return nil
 	}
 
+	// marshal a type using the Marshaler type
+	// if it implements that interface.
+	if marshaler, ok := v.Interface().(Marshaler); ok {
+		bytes, err := marshaler.MarshalBencode()
+		if err != nil {
+			return err
+		}
+
+		_, err = w.Write(bytes)
+		return err
+	}
+
 	//send in a raw message if we have that type
 	if rm, ok := v.Interface().(RawMessage); ok {
 		_, err := io.Copy(w, bytes.NewReader(rm))

But feel free to correct me, in case I'm missing any complexities though.

For the Unmarshaler things get however a bit more complicated. I would propose to again keep the interface as simple as:

// Unmarshaler is the interface implemented by types that can unmarshal
// a bencode description of themselves.
// The input can be assumed to be a valid encoding of a bencode value.
// UnmarshalBencode must copy the bencode data if it wishes to retain the data after returning.
type Unmarshaler interface {
	UnmarshalBencode([]byte) error
}

However implementing it is a bit more complicated than I had imagined, due to the fact that the code doesn't seem to have taken that possibility into account. The std encoding/json package seems to resolve this by having a handy function available called next() which returns the next available JSON value from the available buffer, however such a utility function doesn't seem to be available in your decoder.

So perhaps you have an idea on how we could resolve this?

Thank you for providing this package though, a couple of months ago I was almost implementing my own bencode package from scratch, until I found yours, so this saved me a lot of work, for which lots of thanks! The package works great, But I now have a scenario where I could really use the possibility to provide my own encode/decode logic (using a marshaler/unmarshaler), such that I can encode my struct as a custom string value rather than a dictionary.

Add TextUnmarshaler/TextMarshaler interface support

As we now also support full Marshaler/Unmarshaler interfaces, it would also make sense to support encoding.TextUnmarshaler and encoding.TextMarshaler. Similar to JSON it can be used to automatically decode/encode the value from a bencode string, and let the value take it from there. It's a neat interface, as it allows a type to be (un)marshalled, regardless of the encoding format. Making it much easier than having to support 3 different interfaces for a single type.

nil not being decoded correctly

Seems like a nil values are not properly decoded. Rather than the decoded value being nil, it is initialized with the given type.

Here's a test case to re-produce:

import (
	"testing"
	"github.com/zeebo/bencode"
)

type TT struct {
	Name string
}

type TestStruct struct {
	T *TT
}

func Test_Bencode(t *testing.T) {
	var val TestStruct
	b, err := bencode.EncodeBytes(&val)
	if err != nil {
		t.Fatal(err)
	}

	var v1 TestStruct
	if err = bencode.DecodeBytes(b, &v1); err != nil {
		t.Fatal(err)
	}

	if v1.T != nil {
		t.Fatalf("v1.T should be nil. got: %#v", v1.T)
	}
}

Add EncodeBytes and DecodeBytes functions

There are helper functions for encoding and decoding strings but not for bytes:

func DecodeString(in string, val interface{}) error
func EncodeString(val interface{}) (string, error)

If you don't have any objection, I would like to implement

func DecodeBytes(b []byte, val interface{}) error
func EncodeBytes(val interface{}) ([]byte, error)

functions and send you a pull request, OK?

Add travis CI

Currently travis CI is missing, I would recommend to add it (or any other CI that you would wish to use for this project).

tag bug?

package main

import (
    "fmt"

    "github.com/zeebo/bencode"
)

type Bug struct {
    Name     string `bencode:"name"`
    NameUtf8 string `bencode:"name.utf-8"`
}

func main() {
    b := map[string]string{
        "name":       "name",
        "name.utf-8": "name.utf-8",
    }
    str, _ := bencode.EncodeString(&b)
    fmt.Println(str)

    bug := new(Bug)
    bencode.DecodeString(str, bug)
    fmt.Printf("%+v\n", bug)
}

bencode.RawMessage support

The Go encoding/json package has support for post-processing of data using a type json.RawMessage. When decoding into a struct, if a type is of json.RawMessage, the []byte data is put into that for post-processing. This is useful when you don't know the type in advance (such as in the net/rpc package).

Encode []byte as binary strings, not array of numbers

Pretty much what the title says.

Encoding e.g. []byte{'1','2','3'} results in li49ei50ei51ee, while 3:123 would be much more suitable. Actually, one of the biggest points of bencode is binary safety, i.e. you can encode arbitrary binary strings without escaping or other transformation; encoding []byte the way it is done now is not making advantage of this.

Of course it currently works, however performance could be improved by doing this right.

Workaround: cast every []byte to a string. Not pretty though.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.