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