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  }