]> Sergey Matveev's repositories - btrtrc.git/blob - bencode/api.go
Add bufio.Writer error handling, move Flush to the internal code.
[btrtrc.git] / bencode / api.go
1 package bencode
2
3 import "bytes"
4 import "bufio"
5 import "reflect"
6 import "strconv"
7 import "io"
8
9 //----------------------------------------------------------------------------
10 // Errors
11 //----------------------------------------------------------------------------
12
13 // In case if marshaler cannot encode a type in bencode, it will return this
14 // error. Typical example of such type is float32/float64 which has no bencode
15 // representation
16 type MarshalTypeError struct {
17         Type reflect.Type
18 }
19
20 func (this *MarshalTypeError) Error() string {
21         return "bencode: unsupported type: " + this.Type.String()
22 }
23
24 // Unmarshal argument must be a non-nil value of some pointer type.
25 type UnmarshalInvalidArgError struct {
26         Type reflect.Type
27 }
28
29 func (e *UnmarshalInvalidArgError) Error() string {
30         if e.Type == nil {
31                 return "bencode: Unmarshal(nil)"
32         }
33
34         if e.Type.Kind() != reflect.Ptr {
35                 return "bencode: Unmarshal(non-pointer " + e.Type.String() + ")"
36         }
37         return "bencode: Unmarshal(nil " + e.Type.String() + ")"
38 }
39
40 // Unmarshaler spotted a value that was not appropriate for a given specific Go
41 // 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 type SyntaxError struct {
65         Offset int64  // location of the error
66         what   string // error description
67 }
68
69 func (e *SyntaxError) Error() string {
70         return "bencode: syntax error (offset: " +
71                 strconv.FormatInt(e.Offset, 10) +
72                 "): " + e.what
73 }
74
75 type MarshalerError struct {
76         Type reflect.Type
77         Err  error
78 }
79
80 func (e *MarshalerError) Error() string {
81         return "bencode: error calling MarshalBencode for type " + e.Type.String() + ": " + e.Err.Error()
82 }
83
84 //----------------------------------------------------------------------------
85 // Interfaces
86 //----------------------------------------------------------------------------
87
88 // unused for now (TODO)
89 type Marshaler interface {
90         MarshalBencode() ([]byte, error)
91 }
92
93 // unused for now (TODO)
94 type Unmarshaler interface {
95         UnmarshalBencode([]byte) error
96 }
97
98 //----------------------------------------------------------------------------
99 // Stateless interface
100 //----------------------------------------------------------------------------
101
102 func Marshal(v interface{}) ([]byte, error) {
103         var buf bytes.Buffer
104         e := encoder{Writer: bufio.NewWriter(&buf)}
105         err := e.encode(v)
106         if err != nil {
107                 return nil, err
108         }
109         return buf.Bytes(), nil
110 }
111
112 func Unmarshal(data []byte, v interface{}) error {
113         e := decoder{Reader: bufio.NewReader(bytes.NewBuffer(data))}
114         return e.decode(v)
115 }
116
117 //----------------------------------------------------------------------------
118 // Stateful interface
119 //----------------------------------------------------------------------------
120
121 type Decoder struct {
122         d decoder
123 }
124
125 func NewDecoder(r io.Reader) *Decoder {
126         return &Decoder{decoder{Reader: bufio.NewReader(r)}}
127 }
128
129 func (d *Decoder) Decode(v interface{}) error {
130         return d.d.decode(v)
131 }
132
133 type Encoder struct {
134         e encoder
135 }
136
137 func NewEncoder(w io.Writer) *Encoder {
138         return &Encoder{encoder{Writer: bufio.NewWriter(w)}}
139 }
140
141 func (e *Encoder) Encode(v interface{}) error {
142         err := e.e.encode(v)
143         if err != nil {
144                 return err
145         }
146         return nil
147 }