forked from anacrolix/torrent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi.go
164 lines (136 loc) · 4.38 KB
/
api.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package bencode
import (
"bytes"
"fmt"
"io"
"reflect"
"github.com/anacrolix/missinggo/expect"
)
//----------------------------------------------------------------------------
// Errors
//----------------------------------------------------------------------------
// In case if marshaler cannot encode a type, it will return this error. Typical
// example of such type is float32/float64 which has no bencode representation.
type MarshalTypeError struct {
Type reflect.Type
}
func (e *MarshalTypeError) Error() string {
return "bencode: unsupported type: " + e.Type.String()
}
// Unmarshal argument must be a non-nil value of some pointer type.
type UnmarshalInvalidArgError struct {
Type reflect.Type
}
func (e *UnmarshalInvalidArgError) Error() string {
if e.Type == nil {
return "bencode: Unmarshal(nil)"
}
if e.Type.Kind() != reflect.Ptr {
return "bencode: Unmarshal(non-pointer " + e.Type.String() + ")"
}
return "bencode: Unmarshal(nil " + e.Type.String() + ")"
}
// Unmarshaler spotted a value that was not appropriate for a given Go value.
type UnmarshalTypeError struct {
BencodeTypeName string
UnmarshalTargetType reflect.Type
}
// This could probably be a value type, but we may already have users assuming
// that it's passed by pointer.
func (e *UnmarshalTypeError) Error() string {
return fmt.Sprintf(
"can't unmarshal a bencode %v into a %v",
e.BencodeTypeName,
e.UnmarshalTargetType,
)
}
// Unmarshaler tried to write to an unexported (therefore unwritable) field.
type UnmarshalFieldError struct {
Key string
Type reflect.Type
Field reflect.StructField
}
func (e *UnmarshalFieldError) Error() string {
return "bencode: key \"" + e.Key + "\" led to an unexported field \"" +
e.Field.Name + "\" in type: " + e.Type.String()
}
// Malformed bencode input, unmarshaler failed to parse it.
type SyntaxError struct {
Offset int64 // location of the error
What error // error description
}
func (e *SyntaxError) Error() string {
return fmt.Sprintf("bencode: syntax error (offset: %d): %s", e.Offset, e.What)
}
// A non-nil error was returned after calling MarshalBencode on a type which
// implements the Marshaler interface.
type MarshalerError struct {
Type reflect.Type
Err error
}
func (e *MarshalerError) Error() string {
return "bencode: error calling MarshalBencode for type " + e.Type.String() + ": " + e.Err.Error()
}
// A non-nil error was returned after calling UnmarshalBencode on a type which
// implements the Unmarshaler interface.
type UnmarshalerError struct {
Type reflect.Type
Err error
}
func (e *UnmarshalerError) Error() string {
return "bencode: error calling UnmarshalBencode for type " + e.Type.String() + ": " + e.Err.Error()
}
//----------------------------------------------------------------------------
// Interfaces
//----------------------------------------------------------------------------
// Any type which implements this interface, will be marshaled using the
// specified method.
type Marshaler interface {
MarshalBencode() ([]byte, error)
}
// Any type which implements this interface, will be unmarshaled using the
// specified method.
type Unmarshaler interface {
UnmarshalBencode([]byte) error
}
// Marshal the value 'v' to the bencode form, return the result as []byte and
// an error if any.
func Marshal(v interface{}) ([]byte, error) {
var buf bytes.Buffer
e := Encoder{w: &buf}
err := e.Encode(v)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func MustMarshal(v interface{}) []byte {
b, err := Marshal(v)
expect.Nil(err)
return b
}
// Unmarshal the bencode value in the 'data' to a value pointed by the 'v' pointer, return a non-nil
// error if any. If there are trailing bytes, this results in ErrUnusedTrailingBytes, but the value
// will be valid. It's probably more consistent to use Decoder.Decode if you want to rely on this
// behaviour (inspired by Rust's serde here).
func Unmarshal(data []byte, v interface{}) (err error) {
buf := bytes.NewReader(data)
e := Decoder{r: buf}
err = e.Decode(v)
if err == nil && buf.Len() != 0 {
err = ErrUnusedTrailingBytes{buf.Len()}
}
return
}
type ErrUnusedTrailingBytes struct {
NumUnusedBytes int
}
func (me ErrUnusedTrailingBytes) Error() string {
return fmt.Sprintf("%d unused trailing bytes", me.NumUnusedBytes)
}
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: &scanner{r: r}}
}
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w}
}