@@ -2,162 +2,118 @@ package encoder
22
33import (
44 "fmt"
5+ "unsafe"
56
67 "github.com/IncSW/go-bencode/internal"
78)
89
9- func prepareBuffer (result * []byte , offset int , length int , neededLength int ) int {
10- availableLength := length - offset
10+ //go:linkname memmove runtime.memmove
11+ //go:noescape
12+ func memmove (to unsafe.Pointer , from unsafe.Pointer , n uintptr )
13+
14+ type sliceHeader struct {
15+ data unsafe.Pointer
16+ len int
17+ cap int
18+ }
19+
20+ type Encoder struct {
21+ buffer []byte
22+ length int
23+ offset int
24+ }
25+
26+ //go:nosplit
27+ func (e * Encoder ) grow (neededLength int ) {
28+ availableLength := e .length - e .offset
1129 if availableLength >= neededLength {
12- return length
30+ return
1331 }
14-
15- rate := 1
16- for availableLength < neededLength {
17- rate ++
18- availableLength = length * rate - offset
32+ if e .length == 0 {
33+ if neededLength < 16 {
34+ neededLength = 16
35+ }
36+ e .length = neededLength
37+ availableLength = neededLength
38+ } else {
39+ for availableLength < neededLength {
40+ e .length += e .length
41+ availableLength = e .length - e .offset
42+ }
1943 }
44+ buffer := make ([]byte , e .length )
45+ memmove (
46+ unsafe .Pointer (uintptr ((* sliceHeader )(unsafe .Pointer (& buffer )).data )),
47+ (* sliceHeader )(unsafe .Pointer (& e .buffer )).data ,
48+ uintptr (e .offset ),
49+ )
50+ e .buffer = buffer
51+ }
2052
21- newResult := make ([]byte , length * rate )
22- copy (newResult , (* result )[:length ])
23- length *= rate
24- * result = newResult
53+ //go:nosplit
54+ func (e * Encoder ) write (data []byte ) {
55+ length := len (data )
56+ memmove (
57+ unsafe .Pointer (uintptr ((* sliceHeader )(unsafe .Pointer (& e .buffer )).data )+ uintptr (e .offset )),
58+ (* sliceHeader )(unsafe .Pointer (& data )).data ,
59+ uintptr (length ),
60+ )
61+ e .offset += length
62+ }
2563
26- return length
64+ //go:nosplit
65+ func (e * Encoder ) writeByte (data byte ) {
66+ * (* byte )(unsafe .Pointer (uintptr ((* sliceHeader )(unsafe .Pointer (& e .buffer )).data ) + uintptr (e .offset ))) = data
67+ e .offset ++
2768}
2869
29- func MarshalTo (dst []byte , data interface {}) ([]byte , error ) {
70+ func ( e * Encoder ) EncodeTo (dst []byte , data interface {}) ([]byte , error ) {
3071 if cap (dst ) > len (dst ) {
3172 dst = dst [:cap (dst )]
3273 } else if len (dst ) == 0 {
3374 dst = make ([]byte , 512 )
3475 }
35- length , _ , err := marshal (data , & dst , 0 , len (dst ))
76+ e .buffer = dst
77+ e .length = cap (dst )
78+ err := e .encode (data )
3679 if err != nil {
3780 return nil , err
3881 }
39- return dst [: length ], nil
82+ return e . buffer [: e . offset ], nil
4083}
4184
42- func marshal ( data interface {}, result * [] byte , offset int , length int ) ( int , int , error ) {
85+ func ( e * Encoder ) encode ( data interface {}) error {
4386 switch value := data .(type ) {
4487 case int64 :
45- offset , length = marshalInt (value , result , offset , length )
46- return offset , length , nil
47-
88+ e .encodeInt (value )
4889 case int32 :
49- offset , length = marshalInt (int64 (value ), result , offset , length )
50- return offset , length , nil
51-
90+ e .encodeInt (int64 (value ))
5291 case int16 :
53- offset , length = marshalInt (int64 (value ), result , offset , length )
54- return offset , length , nil
55-
92+ e .encodeInt (int64 (value ))
5693 case int8 :
57- offset , length = marshalInt (int64 (value ), result , offset , length )
58- return offset , length , nil
59-
94+ e .encodeInt (int64 (value ))
6095 case int :
61- offset , length = marshalInt (int64 (value ), result , offset , length )
62- return offset , length , nil
63-
96+ e .encodeInt (int64 (value ))
6497 case uint64 :
65- offset , length = marshalInt (int64 (value ), result , offset , length )
66- return offset , length , nil
67-
98+ e .encodeInt (int64 (value ))
6899 case uint32 :
69- offset , length = marshalInt (int64 (value ), result , offset , length )
70- return offset , length , nil
71-
100+ e .encodeInt (int64 (value ))
72101 case uint16 :
73- offset , length = marshalInt (int64 (value ), result , offset , length )
74- return offset , length , nil
75-
102+ e .encodeInt (int64 (value ))
76103 case uint8 :
77- offset , length = marshalInt (int64 (value ), result , offset , length )
78- return offset , length , nil
79-
104+ e .encodeInt (int64 (value ))
80105 case uint :
81- offset , length = marshalInt (int64 (value ), result , offset , length )
82- return offset , length , nil
83-
106+ e .encodeInt (int64 (value ))
84107 case []byte :
85- offset , length = marshalBytes (value , result , offset , length )
86- return offset , length , nil
87-
108+ e .encodeBytes (value )
88109 case string :
89- offset , length = marshalBytes (internal .S2B (value ), result , offset , length )
90- return offset , length , nil
91-
110+ e .encodeBytes (internal .S2B (value ))
92111 case []interface {}:
93- return marshalList (value , result , offset , length )
94-
112+ return e .encodeList (value )
95113 case map [string ]interface {}:
96- return marshalDictionary (value , result , offset , length )
97-
114+ return e .encodeDictionary (value )
98115 default :
99- return 0 , 0 , fmt .Errorf ("bencode: unsupported type: %T" , value )
100- }
101- }
102-
103- func marshalBytes (data []byte , result * []byte , offset int , length int ) (int , int ) {
104- dataLength := len (data )
105- offset , length = writeInt (int64 (dataLength ), result , offset , length )
106- length = prepareBuffer (result , offset , length , dataLength + 1 )
107- (* result )[offset ] = ':'
108- offset ++
109- copy ((* result )[offset :], data )
110- offset += dataLength
111- return offset , length
112- }
113-
114- func marshalList (data []interface {}, result * []byte , offset int , length int ) (int , int , error ) {
115- length = prepareBuffer (result , offset , length , 1 )
116-
117- (* result )[offset ] = 'l'
118- offset ++
119-
120- for _ , data := range data {
121- var err error
122- offset , length , err = marshal (data , result , offset , length )
123- if err != nil {
124- return 0 , 0 , err
125- }
116+ return fmt .Errorf ("bencode: unsupported type: %T" , value )
126117 }
127-
128- length = prepareBuffer (result , offset , length , 1 )
129-
130- (* result )[offset ] = 'e'
131- offset ++
132-
133- return offset , length , nil
134- }
135-
136- func marshalDictionary (data map [string ]interface {}, result * []byte , offset int , length int ) (int , int , error ) {
137- length = prepareBuffer (result , offset , length , 1 )
138-
139- (* result )[offset ] = 'd'
140- offset ++
141-
142- keys := make ([]string , 0 , len (data ))
143- for key , _ := range data {
144- keys = append (keys , key )
145- }
146- internal .SortStrings (keys )
147-
148- for _ , key := range keys {
149- offset , length = marshalBytes (internal .S2B (key ), result , offset , length )
150- var err error
151- offset , length , err = marshal (data [key ], result , offset , length )
152- if err != nil {
153- return 0 , 0 , err
154- }
155- }
156-
157- length = prepareBuffer (result , offset , length , 1 )
158-
159- (* result )[offset ] = 'e'
160- offset ++
161-
162- return offset , length , nil
118+ return nil
163119}
0 commit comments