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