github.com/anacrolix/torrent@v1.61.0/bencode/api.go (about) 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 dec := Decoder{r: buf} 143 err = dec.Decode(v) 144 if err != nil { 145 return 146 } 147 if buf.Len() != 0 { 148 return ErrUnusedTrailingBytes{buf.Len()} 149 } 150 return dec.ReadEOF() 151 } 152 153 type ErrUnusedTrailingBytes struct { 154 NumUnusedBytes int 155 } 156 157 func (me ErrUnusedTrailingBytes) Error() string { 158 return fmt.Sprintf("%d unused trailing bytes", me.NumUnusedBytes) 159 } 160 161 func NewDecoder(r io.Reader) *Decoder { 162 return &Decoder{r: &scanner{r: r}} 163 } 164 165 func NewEncoder(w io.Writer) *Encoder { 166 return &Encoder{w: w} 167 }