11 "github.com/anacrolix/missinggo"
14 func is_empty_value(v reflect.Value) bool {
15 return missinggo.IsEmptyValue(v)
23 func (e *Encoder) Encode(v interface{}) (err error) {
28 if e := recover(); e != nil {
29 if _, ok := e.(runtime.Error); ok {
39 e.reflect_value(reflect.ValueOf(v))
43 type string_values []reflect.Value
45 func (sv string_values) Len() int { return len(sv) }
46 func (sv string_values) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
47 func (sv string_values) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
48 func (sv string_values) get(i int) string { return sv[i].String() }
50 func (e *Encoder) write(s []byte) {
57 func (e *Encoder) write_string(s string) {
58 _, err := e.WriteString(s)
64 func (e *Encoder) reflect_string(s string) {
65 b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
71 func (e *Encoder) reflect_byte_slice(s []byte) {
72 b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
78 // returns true if the value implements Marshaler interface and marshaling was
80 func (e *Encoder) reflect_marshaler(v reflect.Value) bool {
81 m, ok := v.Interface().(Marshaler)
83 // T doesn't work, try *T
84 if v.Kind() != reflect.Ptr && v.CanAddr() {
85 m, ok = v.Addr().Interface().(Marshaler)
91 if ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
92 data, err := m.MarshalBencode()
94 panic(&MarshalerError{v.Type(), err})
103 func (e *Encoder) reflect_value(v reflect.Value) {
105 if e.reflect_marshaler(v) {
112 e.write_string("i1e")
114 e.write_string("i0e")
116 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
117 b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
121 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
122 b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
127 e.reflect_string(v.String())
130 for _, ef := range encode_fields(v.Type()) {
131 field_value := v.Field(ef.i)
132 if ef.omit_empty && is_empty_value(field_value) {
135 e.reflect_string(ef.tag)
136 e.reflect_value(field_value)
140 if v.Type().Key().Kind() != reflect.String {
141 panic(&MarshalTypeError{v.Type()})
148 sv := string_values(v.MapKeys())
150 for _, key := range sv {
151 e.reflect_string(key.String())
152 e.reflect_value(v.MapIndex(key))
160 if v.Type().Elem().Kind() == reflect.Uint8 {
162 e.reflect_byte_slice(s)
168 for i, n := 0, v.Len(); i < n; i++ {
169 e.reflect_value(v.Index(i))
172 case reflect.Interface:
173 e.reflect_value(v.Elem())
176 v = reflect.Zero(v.Type().Elem())
182 panic(&MarshalTypeError{v.Type()})
186 type encode_field struct {
192 type encode_fields_sort_type []encode_field
194 func (ef encode_fields_sort_type) Len() int { return len(ef) }
195 func (ef encode_fields_sort_type) Swap(i, j int) { ef[i], ef[j] = ef[j], ef[i] }
196 func (ef encode_fields_sort_type) Less(i, j int) bool { return ef[i].tag < ef[j].tag }
199 type_cache_lock sync.RWMutex
200 encode_fields_cache = make(map[reflect.Type][]encode_field)
203 func encode_fields(t reflect.Type) []encode_field {
204 type_cache_lock.RLock()
205 fs, ok := encode_fields_cache[t]
206 type_cache_lock.RUnlock()
211 type_cache_lock.Lock()
212 defer type_cache_lock.Unlock()
213 fs, ok = encode_fields_cache[t]
218 for i, n := 0, t.NumField(); i < n; i++ {
230 tv := f.Tag.Get("bencode")
235 name, opts := parse_tag(tv)
239 ef.omit_empty = opts.contains("omitempty")
243 fss := encode_fields_sort_type(fs)
245 encode_fields_cache[t] = fs