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