12 "github.com/anacrolix/missinggo"
15 func isEmptyValue(v reflect.Value) bool {
16 return missinggo.IsEmptyValue(v)
23 WriteString(string) (int, error)
28 func (e *Encoder) Encode(v interface{}) (err error) {
33 if e := recover(); e != nil {
34 if _, ok := e.(runtime.Error); ok {
44 e.reflectValue(reflect.ValueOf(v))
48 type string_values []reflect.Value
50 func (sv string_values) Len() int { return len(sv) }
51 func (sv string_values) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
52 func (sv string_values) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
53 func (sv string_values) get(i int) string { return sv[i].String() }
55 func (e *Encoder) write(s []byte) {
56 _, err := e.w.Write(s)
62 func (e *Encoder) writeString(s string) {
63 _, err := e.w.WriteString(s)
69 func (e *Encoder) reflectString(s string) {
70 b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
76 func (e *Encoder) reflectByteSlice(s []byte) {
77 b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
83 // returns true if the value implements Marshaler interface and marshaling was
85 func (e *Encoder) reflectMarshaler(v reflect.Value) bool {
86 m, ok := v.Interface().(Marshaler)
88 // T doesn't work, try *T
89 if v.Kind() != reflect.Ptr && v.CanAddr() {
90 m, ok = v.Addr().Interface().(Marshaler)
96 if ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
97 data, err := m.MarshalBencode()
99 panic(&MarshalerError{v.Type(), err})
108 func (e *Encoder) reflectValue(v reflect.Value) {
110 if e.reflectMarshaler(v) {
114 switch t := v.Interface().(type) {
117 e.writeString(t.String())
129 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
130 b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
134 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
135 b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
140 e.reflectString(v.String())
143 for _, ef := range encodeFields(v.Type()) {
144 field_value := v.Field(ef.i)
145 if ef.omit_empty && isEmptyValue(field_value) {
148 e.reflectString(ef.tag)
149 e.reflectValue(field_value)
153 if v.Type().Key().Kind() != reflect.String {
154 panic(&MarshalTypeError{v.Type()})
161 sv := string_values(v.MapKeys())
163 for _, key := range sv {
164 e.reflectString(key.String())
165 e.reflectValue(v.MapIndex(key))
173 if v.Type().Elem().Kind() == reflect.Uint8 {
175 e.reflectByteSlice(s)
181 for i, n := 0, v.Len(); i < n; i++ {
182 e.reflectValue(v.Index(i))
185 case reflect.Interface:
186 e.reflectValue(v.Elem())
189 v = reflect.Zero(v.Type().Elem())
195 panic(&MarshalTypeError{v.Type()})
199 type encodeField struct {
205 type encodeFieldsSortType []encodeField
207 func (ef encodeFieldsSortType) Len() int { return len(ef) }
208 func (ef encodeFieldsSortType) Swap(i, j int) { ef[i], ef[j] = ef[j], ef[i] }
209 func (ef encodeFieldsSortType) Less(i, j int) bool { return ef[i].tag < ef[j].tag }
212 typeCacheLock sync.RWMutex
213 encodeFieldsCache = make(map[reflect.Type][]encodeField)
216 func encodeFields(t reflect.Type) []encodeField {
217 typeCacheLock.RLock()
218 fs, ok := encodeFieldsCache[t]
219 typeCacheLock.RUnlock()
225 defer typeCacheLock.Unlock()
226 fs, ok = encodeFieldsCache[t]
231 for i, n := 0, t.NumField(); i < n; i++ {
243 tv := f.Tag.Get("bencode")
248 name, opts := parseTag(tv)
252 ef.omit_empty = opts.contains("omitempty")
256 fss := encodeFieldsSortType(fs)
258 encodeFieldsCache[t] = fs