github.com/RevenueMonster/sqlike@v1.0.6/sql/codec/registry.go (about) 1 package codec 2 3 import ( 4 "database/sql" 5 "database/sql/driver" 6 "encoding/json" 7 "errors" 8 "reflect" 9 "sync" 10 "time" 11 12 "cloud.google.com/go/civil" 13 "cloud.google.com/go/datastore" 14 "github.com/RevenueMonster/sqlike/reflext" 15 "github.com/RevenueMonster/sqlike/spatial" 16 "github.com/paulmach/orb" 17 "golang.org/x/text/currency" 18 "golang.org/x/text/language" 19 ) 20 21 // Codecer : 22 type Codecer interface { 23 RegisterTypeCodec(t reflect.Type, enc ValueEncoder, dec ValueDecoder) 24 RegisterTypeEncoder(t reflect.Type, enc ValueEncoder) 25 RegisterTypeDecoder(t reflect.Type, dec ValueDecoder) 26 RegisterKindEncoder(k reflect.Kind, enc ValueEncoder) 27 RegisterKindDecoder(k reflect.Kind, dec ValueDecoder) 28 LookupEncoder(v reflect.Value) (ValueEncoder, error) 29 LookupDecoder(t reflect.Type) (ValueDecoder, error) 30 } 31 32 // DefaultMapper : 33 var ( 34 DefaultRegistry = buildDefaultRegistry() 35 sqlScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem() 36 ) 37 38 func buildDefaultRegistry() Codecer { 39 rg := NewRegistry() 40 dec := DefaultDecoders{rg} 41 enc := DefaultEncoders{rg} 42 43 rg.RegisterTypeCodec(reflect.TypeOf([]byte{}), enc.EncodeByte, dec.DecodeByte) 44 rg.RegisterTypeCodec(reflect.TypeOf(language.Tag{}), enc.EncodeStringer, dec.DecodeLanguage) 45 rg.RegisterTypeCodec(reflect.TypeOf(currency.Unit{}), enc.EncodeStringer, dec.DecodeCurrency) 46 rg.RegisterTypeCodec(reflect.TypeOf(time.Time{}), enc.EncodeDateTime, dec.DecodeDateTime) 47 rg.RegisterTypeCodec(reflect.TypeOf(time.Location{}), enc.EncodePointerStringer, dec.DecodeTimeLocation) 48 rg.RegisterTypeCodec(reflect.TypeOf(civil.Date{}), enc.EncodeStringer, dec.DecodeDate) 49 rg.RegisterTypeCodec(reflect.TypeOf(civil.Time{}), enc.EncodeStringer, dec.DecodeTime) 50 rg.RegisterTypeCodec(reflect.TypeOf(sql.RawBytes{}), enc.EncodeRawBytes, dec.DecodeRawBytes) 51 rg.RegisterTypeCodec(reflect.TypeOf(json.RawMessage{}), enc.EncodeJSONRaw, dec.DecodeJSONRaw) 52 rg.RegisterTypeCodec(reflect.TypeOf(orb.Point{}), enc.EncodeSpatial(spatial.Point), dec.DecodePoint) 53 rg.RegisterTypeCodec(reflect.TypeOf(orb.LineString{}), enc.EncodeSpatial(spatial.LineString), dec.DecodeLineString) 54 // fallback support goloquent datastore key 55 rg.RegisterTypeCodec(reflect.TypeOf(datastore.Key{}), enc.EncodeDatastoreKey, dec.DecodeDatastoreKey) 56 57 // rg.RegisterTypeCodec(reflect.TypeOf(orb.Polygon{}), enc.EncodeSpatial(spatial.Polygon), dec.DecodePolygon) 58 // rg.RegisterTypeCodec(reflect.TypeOf(orb.MultiPoint{}), enc.EncodeSpatial(spatial.MultiPoint), dec.DecodeMultiPoint) 59 // rg.RegisterTypeCodec(reflect.TypeOf(orb.MultiLineString{}), enc.EncodeSpatial(spatial.MultiLineString), dec.DecodeMultiLineString) 60 // rg.RegisterTypeCodec(reflect.TypeOf(orb.MultiPolygon{}), enc.EncodeSpatial(spatial.MultiPolygon), dec.DecodeMultiPolygon) 61 62 rg.RegisterKindCodec(reflect.String, enc.EncodeString, dec.DecodeString) 63 rg.RegisterKindCodec(reflect.Bool, enc.EncodeBool, dec.DecodeBool) 64 rg.RegisterKindCodec(reflect.Int, enc.EncodeInt, dec.DecodeInt) 65 rg.RegisterKindCodec(reflect.Int8, enc.EncodeInt, dec.DecodeInt) 66 rg.RegisterKindCodec(reflect.Int16, enc.EncodeInt, dec.DecodeInt) 67 rg.RegisterKindCodec(reflect.Int32, enc.EncodeInt, dec.DecodeInt) 68 rg.RegisterKindCodec(reflect.Int64, enc.EncodeInt, dec.DecodeInt) 69 rg.RegisterKindCodec(reflect.Uint, enc.EncodeUint, dec.DecodeUint) 70 rg.RegisterKindCodec(reflect.Uint8, enc.EncodeUint, dec.DecodeUint) 71 rg.RegisterKindCodec(reflect.Uint16, enc.EncodeUint, dec.DecodeUint) 72 rg.RegisterKindCodec(reflect.Uint32, enc.EncodeUint, dec.DecodeUint) 73 rg.RegisterKindCodec(reflect.Uint64, enc.EncodeUint, dec.DecodeUint) 74 rg.RegisterKindCodec(reflect.Float32, enc.EncodeFloat, dec.DecodeFloat) 75 rg.RegisterKindCodec(reflect.Float64, enc.EncodeFloat, dec.DecodeFloat) 76 rg.RegisterKindCodec(reflect.Ptr, enc.EncodePtr, dec.DecodePtr) 77 rg.RegisterKindCodec(reflect.Struct, enc.EncodeStruct, dec.DecodeStruct) 78 rg.RegisterKindCodec(reflect.Array, enc.EncodeArray, dec.DecodeArray) 79 rg.RegisterKindCodec(reflect.Slice, enc.EncodeArray, dec.DecodeArray) 80 rg.RegisterKindCodec(reflect.Map, enc.EncodeMap, dec.DecodeMap) 81 return rg 82 } 83 84 // Registry : 85 type Registry struct { 86 mutex *sync.Mutex 87 typeEncoders map[reflect.Type]ValueEncoder 88 typeDecoders map[reflect.Type]ValueDecoder 89 kindEncoders map[reflect.Kind]ValueEncoder 90 kindDecoders map[reflect.Kind]ValueDecoder 91 } 92 93 var _ Codecer = (*Registry)(nil) 94 95 // NewRegistry creates a new empty Registry. 96 func NewRegistry() *Registry { 97 return &Registry{ 98 mutex: new(sync.Mutex), 99 typeEncoders: make(map[reflect.Type]ValueEncoder), 100 typeDecoders: make(map[reflect.Type]ValueDecoder), 101 kindEncoders: make(map[reflect.Kind]ValueEncoder), 102 kindDecoders: make(map[reflect.Kind]ValueDecoder), 103 } 104 } 105 106 // RegisterTypeCodec : 107 func (r *Registry) RegisterTypeCodec(t reflect.Type, enc ValueEncoder, dec ValueDecoder) { 108 r.mutex.Lock() 109 defer r.mutex.Unlock() 110 r.typeEncoders[t] = enc 111 r.typeDecoders[t] = dec 112 } 113 114 // RegisterTypeEncoder : 115 func (r *Registry) RegisterTypeEncoder(t reflect.Type, enc ValueEncoder) { 116 r.mutex.Lock() 117 defer r.mutex.Unlock() 118 r.typeEncoders[t] = enc 119 } 120 121 // RegisterTypeDecoder : 122 func (r *Registry) RegisterTypeDecoder(t reflect.Type, dec ValueDecoder) { 123 r.mutex.Lock() 124 defer r.mutex.Unlock() 125 r.typeDecoders[t] = dec 126 } 127 128 // RegisterKindCodec : 129 func (r *Registry) RegisterKindCodec(k reflect.Kind, enc ValueEncoder, dec ValueDecoder) { 130 r.mutex.Lock() 131 defer r.mutex.Unlock() 132 r.kindEncoders[k] = enc 133 r.kindDecoders[k] = dec 134 } 135 136 // RegisterKindEncoder : 137 func (r *Registry) RegisterKindEncoder(k reflect.Kind, enc ValueEncoder) { 138 r.mutex.Lock() 139 defer r.mutex.Unlock() 140 r.kindEncoders[k] = enc 141 } 142 143 // RegisterKindDecoder : 144 func (r *Registry) RegisterKindDecoder(k reflect.Kind, dec ValueDecoder) { 145 r.mutex.Lock() 146 defer r.mutex.Unlock() 147 r.kindDecoders[k] = dec 148 } 149 150 // LookupEncoder : 151 func (r *Registry) LookupEncoder(v reflect.Value) (ValueEncoder, error) { 152 var ( 153 enc ValueEncoder 154 ok bool 155 ) 156 157 if !v.IsValid() { 158 return NilEncoder, nil 159 } 160 161 if _, ok := v.Interface().(driver.Valuer); ok { 162 return encodeValue, nil 163 } 164 165 t := v.Type() 166 enc, ok = r.typeEncoders[t] 167 if ok { 168 return enc, nil 169 } 170 171 enc, ok = r.kindEncoders[t.Kind()] 172 if ok { 173 return enc, nil 174 } 175 return nil, ErrNoEncoder{Type: t} 176 } 177 178 // LookupDecoder : 179 func (r *Registry) LookupDecoder(t reflect.Type) (ValueDecoder, error) { 180 var ( 181 dec ValueDecoder 182 ok bool 183 ) 184 185 ptrType := t 186 if t.Kind() != reflect.Ptr { 187 ptrType = reflect.PtrTo(t) 188 } 189 190 if ptrType.Implements(sqlScanner) { 191 return sqlScannerDecoder, nil 192 } 193 194 dec, ok = r.typeDecoders[t] 195 if ok { 196 return dec, nil 197 } 198 199 dec, ok = r.kindDecoders[t.Kind()] 200 if ok { 201 return dec, nil 202 } 203 return nil, ErrNoDecoder{Type: t} 204 } 205 206 func encodeValue(_ reflext.StructFielder, v reflect.Value) (interface{}, error) { 207 if !v.IsValid() || reflext.IsNull(v) { 208 return nil, nil 209 } 210 x, ok := v.Interface().(driver.Valuer) 211 if !ok { 212 return nil, errors.New("codec: invalid type for assertion") 213 } 214 return x.Value() 215 } 216 217 // NilEncoder : 218 func NilEncoder(_ reflext.StructFielder, _ reflect.Value) (interface{}, error) { 219 return nil, nil 220 } 221 222 func sqlScannerDecoder(it interface{}, v reflect.Value) error { 223 if it == nil { 224 // Avoid from sql.scanner when the value is nil 225 v.Set(reflect.Zero(v.Type())) 226 return nil 227 } 228 229 if v.Kind() != reflect.Ptr { 230 return v.Addr().Interface().(sql.Scanner).Scan(it) 231 } 232 233 return reflext.Init(v).Interface().(sql.Scanner).Scan(it) 234 }