gopkg.in/rethinkdb/rethinkdb-go.v6@v6.2.2/encoding/decoder.go (about) 1 package encoding 2 3 import ( 4 "errors" 5 "reflect" 6 "runtime" 7 "sync" 8 ) 9 10 var byteSliceType = reflect.TypeOf([]byte(nil)) 11 12 type decoderFunc func(dv reflect.Value, sv reflect.Value) error 13 14 // Decode decodes map[string]interface{} into a struct. The first parameter 15 // must be a pointer. 16 func Decode(dst interface{}, src interface{}) (err error) { 17 return decode(dst, src, true) 18 } 19 20 func Merge(dst interface{}, src interface{}) (err error) { 21 return decode(dst, src, false) 22 } 23 24 func decode(dst interface{}, src interface{}, blank bool) (err error) { 25 defer func() { 26 if r := recover(); r != nil { 27 if _, ok := r.(runtime.Error); ok { 28 panic(r) 29 } 30 if v, ok := r.(string); ok { 31 err = errors.New(v) 32 } else { 33 err = r.(error) 34 } 35 } 36 }() 37 38 dv := reflect.ValueOf(dst) 39 sv := reflect.ValueOf(src) 40 if dv.Kind() != reflect.Ptr { 41 return &DecodeTypeError{ 42 DestType: dv.Type(), 43 SrcType: sv.Type(), 44 Reason: "must be a pointer", 45 } 46 } 47 48 dv = dv.Elem() 49 if !dv.CanAddr() { 50 return &DecodeTypeError{ 51 DestType: dv.Type(), 52 SrcType: sv.Type(), 53 Reason: "must be addressable", 54 } 55 } 56 57 return decodeValue(dv, sv, blank) 58 } 59 60 // decodeValue decodes the source value into the destination value 61 func decodeValue(dv, sv reflect.Value, blank bool) error { 62 return valueDecoder(dv, sv, blank)(dv, sv) 63 } 64 65 type decoderCacheKey struct { 66 dt, st reflect.Type 67 } 68 69 var decoderCache struct { 70 sync.RWMutex 71 m map[decoderCacheKey]decoderFunc 72 } 73 74 func valueDecoder(dv, sv reflect.Value, blank bool) decoderFunc { 75 if !sv.IsValid() { 76 return invalidValueDecoder 77 } 78 79 if dv.IsValid() { 80 dv = indirect(dv, false) 81 if sv.Kind() == reflect.Ptr { 82 sv = indirect(sv, false) 83 dv.Set(sv) 84 } else if blank { 85 dv.Set(reflect.Zero(dv.Type())) 86 } 87 } 88 89 return typeDecoder(dv.Type(), sv.Type(), blank) 90 } 91 92 func typeDecoder(dt, st reflect.Type, blank bool) decoderFunc { 93 decoderCache.RLock() 94 f := decoderCache.m[decoderCacheKey{dt, st}] 95 decoderCache.RUnlock() 96 if f != nil { 97 return f 98 } 99 100 // To deal with recursive types, populate the map with an 101 // indirect func before we build it. This type waits on the 102 // real func (f) to be ready and then calls it. This indirect 103 // func is only used for recursive types. 104 decoderCache.Lock() 105 var wg sync.WaitGroup 106 wg.Add(1) 107 decoderCache.m[decoderCacheKey{dt, st}] = func(dv, sv reflect.Value) error { 108 wg.Wait() 109 return f(dv, sv) 110 } 111 decoderCache.Unlock() 112 113 // Compute fields without lock. 114 // Might duplicate effort but won't hold other computations back. 115 f = newTypeDecoder(dt, st, blank) 116 wg.Done() 117 decoderCache.Lock() 118 decoderCache.m[decoderCacheKey{dt, st}] = f 119 decoderCache.Unlock() 120 return f 121 } 122 123 // indirect walks down v allocating pointers as needed, 124 // until it gets to a non-pointer. 125 func indirect(v reflect.Value, decodeNull bool) reflect.Value { 126 // If v is a named type and is addressable, 127 // start with its address, so that if the type has pointer methods, 128 // we find them. 129 if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { 130 v = v.Addr() 131 } 132 for { 133 // Load value from interface, but only if the result will be 134 // usefully addressable. 135 if v.Kind() == reflect.Interface && !v.IsNil() { 136 e := v.Elem() 137 if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodeNull || e.Elem().Kind() == reflect.Ptr) { 138 v = e 139 continue 140 } 141 } 142 143 if v.Kind() != reflect.Ptr { 144 break 145 } 146 147 if v.IsNil() { 148 v.Set(reflect.New(v.Type().Elem())) 149 } 150 v = v.Elem() 151 } 152 return v 153 }