12 "github.com/anacrolix/missinggo"
15 func isEmptyValue(v reflect.Value) bool {
16 return missinggo.IsEmptyValue(v)
24 func (e *Encoder) Encode(v interface{}) (err error) {
29 if e := recover(); e != nil {
30 if _, ok := e.(runtime.Error); ok {
40 e.reflectValue(reflect.ValueOf(v))
44 type stringValues []reflect.Value
46 func (sv stringValues) Len() int { return len(sv) }
47 func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
48 func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
49 func (sv stringValues) get(i int) string { return sv[i].String() }
51 func (e *Encoder) write(s []byte) {
52 _, err := e.w.Write(s)
58 func (e *Encoder) writeString(s string) {
60 n := copy(e.scratch[:], s)
62 e.write(e.scratch[:n])
66 func (e *Encoder) reflectString(s string) {
67 e.writeStringPrefix(int64(len(s)))
71 func (e *Encoder) writeStringPrefix(l int64) {
72 b := strconv.AppendInt(e.scratch[:0], l, 10)
77 func (e *Encoder) reflectByteSlice(s []byte) {
78 e.writeStringPrefix(int64(len(s)))
82 // Returns true if the value implements Marshaler interface and marshaling was
84 func (e *Encoder) reflectMarshaler(v reflect.Value) bool {
85 if !v.Type().Implements(marshalerType) {
86 if v.Kind() != reflect.Ptr && v.CanAddr() && v.Addr().Type().Implements(marshalerType) {
92 m := v.Interface().(Marshaler)
93 data, err := m.MarshalBencode()
95 panic(&MarshalerError{v.Type(), err})
101 var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
103 func (e *Encoder) reflectValue(v reflect.Value) {
105 if e.reflectMarshaler(v) {
109 if v.Type() == bigIntType {
111 bi := v.Interface().(big.Int)
112 e.writeString(bi.String())
124 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
126 b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
129 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
131 b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
135 e.reflectString(v.String())
138 for _, ef := range getEncodeFields(v.Type()) {
139 fieldValue := ef.i(v)
140 if !fieldValue.IsValid() {
143 if ef.omitEmpty && isEmptyValue(fieldValue) {
146 e.reflectString(ef.tag)
147 e.reflectValue(fieldValue)
151 if v.Type().Key().Kind() != reflect.String {
152 panic(&MarshalTypeError{v.Type()})
159 sv := stringValues(v.MapKeys())
161 for _, key := range sv {
162 e.reflectString(key.String())
163 e.reflectValue(v.MapIndex(key))
166 case reflect.Slice, reflect.Array:
168 case reflect.Interface:
169 e.reflectValue(v.Elem())
172 v = reflect.Zero(v.Type().Elem())
178 panic(&MarshalTypeError{v.Type()})
182 func (e *Encoder) reflectSequence(v reflect.Value) {
183 // Use bencode string-type
184 if v.Type().Elem().Kind() == reflect.Uint8 {
185 if v.Kind() != reflect.Slice {
186 // Can't use []byte optimization
188 e.writeStringPrefix(int64(v.Len()))
189 for i := 0; i < v.Len(); i++ {
191 b[0] = byte(v.Index(i).Uint())
196 v = v.Slice(0, v.Len())
199 e.reflectByteSlice(s)
207 for i, n := 0, v.Len(); i < n; i++ {
208 e.reflectValue(v.Index(i))
213 type encodeField struct {
214 i func(v reflect.Value) reflect.Value
219 type encodeFieldsSortType []encodeField
221 func (ef encodeFieldsSortType) Len() int { return len(ef) }
222 func (ef encodeFieldsSortType) Swap(i, j int) { ef[i], ef[j] = ef[j], ef[i] }
223 func (ef encodeFieldsSortType) Less(i, j int) bool { return ef[i].tag < ef[j].tag }
226 typeCacheLock sync.RWMutex
227 encodeFieldsCache = make(map[reflect.Type][]encodeField)
230 func getEncodeFields(t reflect.Type) []encodeField {
231 typeCacheLock.RLock()
232 fs, ok := encodeFieldsCache[t]
233 typeCacheLock.RUnlock()
237 fs = makeEncodeFields(t)
239 defer typeCacheLock.Unlock()
240 encodeFieldsCache[t] = fs
244 func makeEncodeFields(t reflect.Type) (fs []encodeField) {
245 for _i, n := 0, t.NumField(); _i < n; _i++ {
253 if t.Kind() == reflect.Ptr {
256 anonEFs := makeEncodeFields(t)
257 for aefi := range anonEFs {
258 anonEF := anonEFs[aefi]
259 bottomField := anonEF
260 bottomField.i = func(v reflect.Value) reflect.Value {
262 if v.Kind() == reflect.Ptr {
264 // This will skip serializing this value.
265 return reflect.Value{}
271 fs = append(fs, bottomField)
276 ef.i = func(v reflect.Value) reflect.Value {
288 ef.omitEmpty = tv.OmitEmpty()
291 fss := encodeFieldsSortType(fs)