diff --git a/README.md b/README.md index 33d384b..a35ae69 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ See [docs][pkg-url]. ## Install -Go version 1.15+ +Go version 1.18+ ``` go get github.com/cristalhq/bencode @@ -29,7 +29,7 @@ Marshaling into Bencode ```go // data to process, most of the types are supported -var data interface{} = map[string]interface{}{ +var data any = map[string]any{ "1": 42, "hello": "world", "foo": []string{"bar", "baz"}, @@ -51,7 +51,7 @@ checkErr(err) Unmarshaling from Bencode ```go -var data interface{} +var data any buf := []byte("li1ei42ee") diff --git a/bencode.go b/bencode.go index 00e4a1f..5f310a8 100644 --- a/bencode.go +++ b/bencode.go @@ -11,7 +11,7 @@ type Marshaler interface { } // Marshal returns bencode encoding of v. -func Marshal(v interface{}) ([]byte, error) { +func Marshal(v any) ([]byte, error) { buf := &bytes.Buffer{} if err := NewEncoder(buf).Encode(v); err != nil { return nil, err @@ -20,7 +20,7 @@ func Marshal(v interface{}) ([]byte, error) { } // MarshalTo returns bencode encoding of v written to dst. -func MarshalTo(dst []byte, v interface{}) ([]byte, error) { +func MarshalTo(dst []byte, v any) ([]byte, error) { enc := &Encoder{buf: dst} if err := enc.marshal(v); err != nil { return nil, err @@ -36,7 +36,7 @@ type Unmarshaler interface { // Unmarshal parses the bencoded data and stores the result // in the value pointed to by v. -func Unmarshal(data []byte, v interface{}) error { +func Unmarshal(data []byte, v any) error { d := NewDecodeBytes(data) if err := d.Decode(v); err != nil { return err @@ -49,7 +49,7 @@ func Unmarshal(data []byte, v interface{}) error { // Example: // // bencode.A{"hello", "world", 3.14159, bencode.D{{"foo", 12345}}} -type A []interface{} +type A []any // D is an ordered representation of a Bencode document. // @@ -61,7 +61,7 @@ type D []e // e represents a Bencode element for a D. It is usually used inside a D. type e struct { K string - V interface{} + V any } // M is an unordered representation of a Bencode document. @@ -69,4 +69,4 @@ type e struct { // Example usage: // // bencode.M{"hello": "world", "foo": "bar", "pi": 3.14159} -type M map[string]interface{} +type M map[string]any diff --git a/decode.go b/decode.go index 7797dca..99051fc 100644 --- a/decode.go +++ b/decode.go @@ -33,7 +33,7 @@ func NewDecodeBytes(src []byte) *Decoder { } // Decode writes the Bencode encoding of v to the stream. -func (d *Decoder) Decode(v interface{}) error { +func (d *Decoder) Decode(v any) error { switch v.(type) { case nil: return errors.New("bencode: cannot marshal into nil") @@ -61,20 +61,20 @@ func (d *Decoder) Decode(v interface{}) error { return d.writeResult(v, got) } -func (d *Decoder) writeResult(v, got interface{}) error { +func (d *Decoder) writeResult(v, got any) error { switch v := v.(type) { - case *interface{}: // catch any type + case *any: // catch any type *v = got - case *map[string]interface{}: - val, ok := got.(map[string]interface{}) + case *map[string]any: + val, ok := got.(map[string]any) if !ok { return fmt.Errorf("bencode: cannot decode %T into map", got) } *v = val - case *[]interface{}: - val, ok := got.([]interface{}) + case *[]any: + val, ok := got.([]any) if !ok { return fmt.Errorf("bencode: cannot decode %T into list", got) } @@ -86,7 +86,7 @@ func (d *Decoder) writeResult(v, got interface{}) error { return nil } -func (d *Decoder) unmarshal() (interface{}, error) { +func (d *Decoder) unmarshal() (any, error) { switch d.data[d.cursor] { case 'i': return d.unmarshalInt() @@ -115,8 +115,8 @@ func (d *Decoder) unmarshalInt() (int64, error) { return integer, nil } -func (d *Decoder) unmarshalMap() (interface{}, error) { - dictionary := make(map[string]interface{}) +func (d *Decoder) unmarshalMap() (any, error) { + dictionary := make(map[string]any) d.cursor++ for { if d.cursor == d.length { @@ -141,8 +141,8 @@ func (d *Decoder) unmarshalMap() (interface{}, error) { } } -func (d *Decoder) unmarshalList() (interface{}, error) { - list := make([]interface{}, 0) +func (d *Decoder) unmarshalList() (any, error) { + list := make([]any, 0) d.cursor++ for { if d.cursor == d.length { diff --git a/decode_test.go b/decode_test.go index 17addf3..efd6f19 100644 --- a/decode_test.go +++ b/decode_test.go @@ -8,7 +8,7 @@ import ( type unmarshalTestCase struct { input string - want interface{} + want any wantErr bool } @@ -89,58 +89,58 @@ func TestUnmarshalSlice(t *testing.T) { tcs := []unmarshalTestCase{ { `le`, - []interface{}{}, + []any{}, false, }, { `li1ei2ei3ee`, - []interface{}{int64(1), int64(2), int64(3)}, + []any{int64(1), int64(2), int64(3)}, false, }, { `l3:foo3:bar3:baze`, - []interface{}{[]byte("foo"), []byte("bar"), []byte("baz")}, + []any{[]byte("foo"), []byte("bar"), []byte("baz")}, false, }, { `li1e3:fooi2e3:bare`, - []interface{}{int64(1), []byte("foo"), int64(2), []byte("bar")}, + []any{int64(1), []byte("foo"), int64(2), []byte("bar")}, false, }, { `li1el3:baree`, - []interface{}{int64(1), []interface{}{[]byte("bar")}}, + []any{int64(1), []any{[]byte("bar")}}, false, }, { `l3:fooe`, - []interface{}{[]byte("foo")}, + []any{[]byte("foo")}, false, }, { `l3:foo6:barbaze`, - []interface{}{[]byte("foo"), []byte("barbaz")}, + []any{[]byte("foo"), []byte("barbaz")}, false, }, { `l3:foo6:barbaz2:goe`, - []interface{}{[]byte("foo"), []byte("barbaz"), []byte("go")}, + []any{[]byte("foo"), []byte("barbaz"), []byte("go")}, false, }, { `l3:fooi20ee`, - []interface{}{[]byte("foo"), int64(20)}, + []any{[]byte("foo"), int64(20)}, false, }, { `li90ei20ee`, - []interface{}{int64(90), int64(20)}, + []any{int64(90), int64(20)}, false, }, { `ll3:foo3:barei20ee`, - []interface{}{ - []interface{}{ + []any{ + []any{ []byte("foo"), []byte("bar"), }, @@ -150,7 +150,7 @@ func TestUnmarshalSlice(t *testing.T) { }, { `l5:024683:acee`, - []interface{}{ + []any{ []byte{'0', '2', '4', '6', '8'}, []byte{'a', 'c', 'e'}, }, @@ -158,12 +158,12 @@ func TestUnmarshalSlice(t *testing.T) { }, { `ld1:ai0e1:bi1eed1:ci2e1:di3eee`, - []interface{}{ - map[string]interface{}{ + []any{ + map[string]any{ "a": int64(0), "b": int64(1), }, - map[string]interface{}{ + map[string]any{ "c": int64(2), "d": int64(3), }, @@ -178,26 +178,26 @@ func TestUnmarshalSlice(t *testing.T) { // tcs := []unmarshalTestCase{ // { // `le`, -// [...]interface{}{}, +// [...]any{}, // false, // }, // { // `li1ei2ei3ee`, -// [...]interface{}{1, 2, 3}, +// [...]any{1, 2, 3}, // false, // }, // { -// [...]interface{}{"foo", "bar", "baz"}, +// [...]any{"foo", "bar", "baz"}, // `l3:foo3:bar3:baze`, // false, // }, // { -// [...]interface{}{1, "foo", 2, "bar"}, +// [...]any{1, "foo", 2, "bar"}, // `li1e3:fooi2e3:bare`, // false, // }, // { -// [...]interface{}{1, [...]interface{}{"bar"}}, +// [...]any{1, [...]any{"bar"}}, // `li1el3:baree`, // false, // }, @@ -219,17 +219,17 @@ func TestUnmarshalMap(t *testing.T) { tcs := []unmarshalTestCase{ { `de`, - map[string]interface{}{}, + map[string]any{}, false, }, { `d1:1i2e1:4i5ee`, - map[string]interface{}{"1": int64(2), "4": int64(5)}, + map[string]any{"1": int64(2), "4": int64(5)}, false, }, { "d1:1i1e3:123i123e1:3i3ee", - map[string]interface{}{ + map[string]any{ "1": int64(1), "3": int64(3), "123": int64(123), @@ -238,7 +238,7 @@ func TestUnmarshalMap(t *testing.T) { }, { "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", - map[string]interface{}{ + map[string]any{ "publisher": []byte("bob"), "publisher-webpage": []byte("www.example.com"), "publisher.location": []byte("home"), @@ -247,12 +247,12 @@ func TestUnmarshalMap(t *testing.T) { }, { "d1:13:onee", - map[string]interface{}{"1": []byte("one")}, + map[string]any{"1": []byte("one")}, false, }, { "d1:13:one3:two1:2e", - map[string]interface{}{ + map[string]any{ "1": []byte("one"), "two": []byte("2"), }, @@ -260,9 +260,9 @@ func TestUnmarshalMap(t *testing.T) { }, { `d1:ali0ei1ee1:bli2ei3eee`, - map[string]interface{}{ - "a": []interface{}{int64(0), int64(1)}, - "b": []interface{}{int64(2), int64(3)}, + map[string]any{ + "a": []any{int64(0), int64(1)}, + "b": []any{int64(2), int64(3)}, }, false, }, @@ -274,7 +274,7 @@ func testLoopUnmarshal(t *testing.T, tcs []unmarshalTestCase) { t.Helper() for i, test := range tcs { - var got interface{} + var got any err := Unmarshal([]byte(test.input), &got) if err != nil { if test.wantErr { @@ -292,7 +292,7 @@ func testLoopUnmarshal(t *testing.T, tcs []unmarshalTestCase) { var unmarshalBenchData = []byte("d4:infod6:lengthi170917888e12:piece lengthi262144e4:name30:debian-8.8.0-arm64-netinst.isoe8:announce38:udp://tracker.publicbt.com:80/announce13:announce-listll38:udp://tracker.publicbt.com:80/announceel44:udp://tracker.openbittorrent.com:80/announceee7:comment33:Debian CD from cdimage.debian.orge") func Benchmark_Unmarshal(b *testing.B) { - var res interface{} + var res any b.ReportAllocs() for n := 0; n < b.N; n++ { err := NewDecodeBytes(unmarshalBenchData).Decode(&res) @@ -306,7 +306,7 @@ func Benchmark_Unmarshal(b *testing.B) { } func Benchmark_UnmarshalReader(b *testing.B) { - var res interface{} + var res any b.ReportAllocs() for n := 0; n < b.N; n++ { r := bytes.NewReader(unmarshalBenchData) diff --git a/encode.go b/encode.go index eb35d88..d2d5e76 100644 --- a/encode.go +++ b/encode.go @@ -30,7 +30,7 @@ func NewEncoderWithBuffer(w io.Writer, buf []byte) *Encoder { } // Encode writes the Bencode encoding of v to the stream. -func (e *Encoder) Encode(v interface{}) error { +func (e *Encoder) Encode(v any) error { e.buf = e.buf[:0] if err := e.marshal(v); err != nil { return fmt.Errorf("bencode: encode failed: %w", err) @@ -39,7 +39,7 @@ func (e *Encoder) Encode(v interface{}) error { return err } -func (e *Encoder) marshal(v interface{}) error { +func (e *Encoder) marshal(v any) error { switch v := v.(type) { case []byte: e.marshalBytes(v) @@ -53,10 +53,10 @@ func (e *Encoder) marshal(v interface{}) error { case A: return e.marshalSlice(v) - case map[string]interface{}: + case map[string]any: return e.marshalDictionary(v) - case []interface{}: + case []any: return e.marshalSlice(v) case int, int8, int16, int32, int64: @@ -113,7 +113,7 @@ func (e *Encoder) marshalString(s string) { e.buf = append(e.buf, s...) } -func (e *Encoder) marshalIntGen(val interface{}) { +func (e *Encoder) marshalIntGen(val any) { var num int64 switch val := val.(type) { case int64: @@ -327,7 +327,7 @@ func (e *Encoder) marshalDictionaryNew(dict D) error { return nil } -func (e *Encoder) marshalDictionary(dict map[string]interface{}) error { +func (e *Encoder) marshalDictionary(dict map[string]any) error { if len(dict) == 0 { e.buf = append(e.buf, "de"...) return nil @@ -360,7 +360,7 @@ func (e *Encoder) marshalDictionary(dict map[string]interface{}) error { return nil } -func (e *Encoder) marshalSlice(v []interface{}) error { +func (e *Encoder) marshalSlice(v []any) error { if len(v) == 0 { e.buf = append(e.buf, "le"...) return nil diff --git a/encode_test.go b/encode_test.go index eebacc3..1d10a56 100644 --- a/encode_test.go +++ b/encode_test.go @@ -5,7 +5,7 @@ import ( ) type marshalTestCase struct { - val interface{} + val any want string wantErr bool } @@ -94,21 +94,21 @@ func TestMarshalByteArrayAsString(t *testing.T) { func TestMarshalSlice(t *testing.T) { tcs := []marshalTestCase{ - {[]interface{}{}, `le`, false}, - {[]interface{}{1, 2, 3}, `li1ei2ei3ee`, false}, - {[]interface{}{"foo", "bar", "baz"}, `l3:foo3:bar3:baze`, false}, - {[]interface{}{1, "foo", 2, "bar"}, `li1e3:fooi2e3:bare`, false}, - {[]interface{}{1, []interface{}{"bar"}}, `li1el3:baree`, false}, + {[]any{}, `le`, false}, + {[]any{1, 2, 3}, `li1ei2ei3ee`, false}, + {[]any{"foo", "bar", "baz"}, `l3:foo3:bar3:baze`, false}, + {[]any{1, "foo", 2, "bar"}, `li1e3:fooi2e3:bare`, false}, + {[]any{1, []any{"bar"}}, `li1el3:baree`, false}, {[]string(nil), `le`, false}, {[]string{}, `le`, false}, {[]string{"foo"}, `l3:fooe`, false}, {[]string{"foo", "barbaz"}, `l3:foo6:barbaze`, false}, {[]string{"foo", "barbaz", "go"}, `l3:foo6:barbaz2:goe`, false}, - {(*[]interface{})(nil), ``, false}, - {[]interface{}{"foo", 20}, `l3:fooi20ee`, false}, + {(*[]any)(nil), ``, false}, + {[]any{"foo", 20}, `l3:fooi20ee`, false}, {A{90, 20}, `li90ei20ee`, false}, {A{"hello", "world", 1020304050, D{{"foo", 12345}}}, "l5:hello5:worldi1020304050ed3:fooi12345eee", false}, - {[]interface{}{[]interface{}{"foo", "bar"}, 20}, `ll3:foo3:barei20ee`, false}, + {[]any{[]any{"foo", "bar"}, 20}, `ll3:foo3:barei20ee`, false}, { []map[string]int{ {"a": 0, "b": 1}, @@ -129,11 +129,11 @@ func TestMarshalSlice(t *testing.T) { func TestMarshalArray(t *testing.T) { tcs := []marshalTestCase{ - {[...]interface{}{}, `le`, false}, - {[...]interface{}{1, 2, 3}, `li1ei2ei3ee`, false}, - {[...]interface{}{"foo", "bar", "baz"}, `l3:foo3:bar3:baze`, false}, - {[...]interface{}{1, "foo", 2, "bar"}, `li1e3:fooi2e3:bare`, false}, - {[...]interface{}{1, [...]interface{}{"bar"}}, `li1el3:baree`, false}, + {[...]any{}, `le`, false}, + {[...]any{1, 2, 3}, `li1ei2ei3ee`, false}, + {[...]any{"foo", "bar", "baz"}, `l3:foo3:bar3:baze`, false}, + {[...]any{1, "foo", 2, "bar"}, `li1e3:fooi2e3:bare`, false}, + {[...]any{1, [...]any{"bar"}}, `li1el3:baree`, false}, {[...]int{0, 1, 2}, "li0ei1ei2ee", false}, {[...]float32{10, 20, 30}, "li1092616192ei1101004800ei1106247680ee", false}, } @@ -162,7 +162,7 @@ func TestMarshalMap(t *testing.T) { "d1:13:onee", false, }, { - map[string]interface{}{"1": "one", "two": "2"}, + map[string]any{"1": "one", "two": "2"}, "d1:13:one3:two1:2e", false, }, { @@ -251,18 +251,18 @@ func testLoopMarshal(t *testing.T, tcs []marshalTestCase) { } } -var marshalBenchData = map[string]interface{}{ +var marshalBenchData = map[string]any{ "announce": ("udp://tracker.publicbt.com:80/announce"), - "announce-list": []interface{}{ - []interface{}{("udp://tracker.publicbt.com:80/announce")}, - []interface{}{[]byte("udp://tracker.openbittorrent.com:80/announce")}, - []interface{}{ + "announce-list": []any{ + []any{("udp://tracker.publicbt.com:80/announce")}, + []any{[]byte("udp://tracker.openbittorrent.com:80/announce")}, + []any{ "udp://tracker.openbittorrent.com:80/announce", "udp://tracker.openbittorrent.com:80/announce", }, }, "comment": []byte("Debian CD from cdimage.debian.org"), - "info": map[string]interface{}{ + "info": map[string]any{ "name": []byte("debian-8.8.0-arm64-netinst.iso"), "length": 170917888, "piece length": 262144, diff --git a/example_test.go b/example_test.go index fb89c34..165f79c 100644 --- a/example_test.go +++ b/example_test.go @@ -9,7 +9,7 @@ import ( func ExampleMarshal() { // data to process, most of the types are supported - var data interface{} = map[string]interface{}{ + var data any = map[string]any{ "1": 42, "hello": "world", "foo": []string{"bar", "baz"}, @@ -29,7 +29,7 @@ func ExampleMarshal() { } func ExampleMarshalTo() { - var data interface{} = map[string]interface{}{ + var data any = map[string]any{ "1": 42, "hello": "world", "foo": []string{"bar", "baz"}, @@ -46,7 +46,7 @@ func ExampleMarshalTo() { } func ExampleUnmarshal() { - var data interface{} + var data any buf := []byte("li1ei42ee") diff --git a/fuzz.go b/fuzz.go index 69867ef..7e482cc 100644 --- a/fuzz.go +++ b/fuzz.go @@ -12,7 +12,7 @@ package bencode func Fuzz(data []byte) int { - var dst interface{} + var dst any if err := Unmarshal(data, &dst); err != nil { return 0 diff --git a/go.mod b/go.mod index ee7f5e5..5bbff7b 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/cristalhq/bencode -go 1.15 +go 1.18 diff --git a/pool.go b/pool.go index d590684..7572d12 100644 --- a/pool.go +++ b/pool.go @@ -7,7 +7,7 @@ import ( const strSliceLen = 20 var strslicePool = sync.Pool{ - New: func() interface{} { + New: func() any { var j [strSliceLen]string return &j },