github.com/RevenueMonster/sqlike@v1.0.6/sql/codec/encoder.go (about)

     1  package codec
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql"
     6  	"encoding/base64"
     7  	"encoding/json"
     8  	"fmt"
     9  	"net/url"
    10  	"reflect"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  
    15  	"cloud.google.com/go/datastore"
    16  	"github.com/RevenueMonster/sqlike/reflext"
    17  	"github.com/RevenueMonster/sqlike/spatial"
    18  	"github.com/paulmach/orb"
    19  	"github.com/paulmach/orb/encoding/wkt"
    20  
    21  	"github.com/RevenueMonster/sqlike/jsonb"
    22  )
    23  
    24  // DefaultEncoders :
    25  type DefaultEncoders struct {
    26  	codec *Registry
    27  }
    28  
    29  // EncodeByte :
    30  func (enc DefaultEncoders) EncodeByte(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
    31  	b := v.Bytes()
    32  	if b == nil {
    33  		return make([]byte, 0), nil
    34  	}
    35  	x := base64.StdEncoding.EncodeToString(b)
    36  	return []byte(x), nil
    37  }
    38  
    39  // EncodeRawBytes :
    40  func (enc DefaultEncoders) EncodeRawBytes(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
    41  	return sql.RawBytes(v.Bytes()), nil
    42  }
    43  
    44  // EncodeJSONRaw :
    45  func (enc DefaultEncoders) EncodeJSONRaw(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
    46  	if v.IsNil() {
    47  		return []byte("null"), nil
    48  	}
    49  	buf := new(bytes.Buffer)
    50  	if err := json.Compact(buf, v.Bytes()); err != nil {
    51  		return nil, err
    52  	}
    53  	if buf.Len() == 0 {
    54  		return []byte(`{}`), nil
    55  	}
    56  	return json.RawMessage(buf.Bytes()), nil
    57  }
    58  
    59  // EncodeStringer :
    60  func (enc DefaultEncoders) EncodeStringer(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
    61  	x := v.Interface().(fmt.Stringer)
    62  	return x.String(), nil
    63  }
    64  
    65  // EncodePointerStringer :
    66  func (enc DefaultEncoders) EncodePointerStringer(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
    67  	x := v.Addr().Interface().(fmt.Stringer)
    68  	return x.String(), nil
    69  }
    70  
    71  // EncodeDateTime :
    72  func (enc DefaultEncoders) EncodeDateTime(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
    73  	x := v.Interface().(time.Time)
    74  	// if x.IsZero() {
    75  	// 	x, _ = time.Parse(time.RFC3339, "1970-01-01T08:00:00Z")
    76  	// 	return x, nil
    77  	// }
    78  	// convert to UTC before storing into DB
    79  	return x.UTC(), nil
    80  }
    81  
    82  // EncodeSpatial :
    83  func (enc DefaultEncoders) EncodeSpatial(st spatial.Type) ValueEncoder {
    84  	return func(sf reflext.StructFielder, v reflect.Value) (interface{}, error) {
    85  		if reflext.IsZero(v) {
    86  			return nil, nil
    87  		}
    88  		x := v.Interface().(orb.Geometry)
    89  		var srid uint
    90  		if sf != nil {
    91  			tag, ok := sf.Tag().LookUp("srid")
    92  			if ok {
    93  				integer, _ := strconv.Atoi(tag)
    94  				if integer > 0 {
    95  					srid = uint(integer)
    96  				}
    97  			}
    98  		}
    99  		return spatial.Geometry{
   100  			Type: st,
   101  			SRID: srid,
   102  			WKT:  wkt.MarshalString(x),
   103  		}, nil
   104  	}
   105  }
   106  
   107  // EncodeString :
   108  func (enc DefaultEncoders) EncodeString(sf reflext.StructFielder, v reflect.Value) (interface{}, error) {
   109  	str := v.String()
   110  	if str == "" && sf != nil {
   111  		tag := sf.Tag()
   112  		if val, ok := tag.LookUp("enum"); ok {
   113  			enums := strings.Split(val, "|")
   114  			if len(enums) > 0 {
   115  				return enums[0], nil
   116  			}
   117  		}
   118  	}
   119  	return str, nil
   120  }
   121  
   122  // EncodeBool :
   123  func (enc DefaultEncoders) EncodeBool(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   124  	return v.Bool(), nil
   125  }
   126  
   127  // EncodeInt :
   128  func (enc DefaultEncoders) EncodeInt(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   129  	return v.Int(), nil
   130  }
   131  
   132  // EncodeUint :
   133  func (enc DefaultEncoders) EncodeUint(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   134  	return v.Uint(), nil
   135  }
   136  
   137  // EncodeFloat :
   138  func (enc DefaultEncoders) EncodeFloat(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   139  	return v.Float(), nil
   140  }
   141  
   142  // EncodePtr :
   143  func (enc *DefaultEncoders) EncodePtr(sf reflext.StructFielder, v reflect.Value) (interface{}, error) {
   144  	if !v.IsValid() || v.IsNil() {
   145  		return nil, nil
   146  	}
   147  	v = v.Elem()
   148  	encoder, err := enc.codec.LookupEncoder(v)
   149  	if err != nil {
   150  		return nil, err
   151  	}
   152  	return encoder(sf, v)
   153  }
   154  
   155  // EncodeStruct :
   156  func (enc DefaultEncoders) EncodeStruct(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   157  	return jsonb.Marshal(v)
   158  }
   159  
   160  // EncodeArray :
   161  func (enc DefaultEncoders) EncodeArray(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   162  	return jsonb.Marshal(v)
   163  }
   164  
   165  // EncodeMap :
   166  func (enc DefaultEncoders) EncodeMap(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   167  	if v.IsNil() {
   168  		return string("null"), nil
   169  	}
   170  
   171  	// t := v.Type()
   172  	// k := t.Key()
   173  	// if k.Kind() != reflect.String {
   174  	// 	return nil, fmt.Errorf("codec: unsupported data type %q for map key, it must be string", k.Kind())
   175  	// }
   176  	// k = t.Elem()
   177  	// if !isBaseType(k) {
   178  	// 	return nil, fmt.Errorf("codec: unsupported data type %q for map value", k.Kind())
   179  	// }
   180  	return jsonb.Marshal(v)
   181  }
   182  
   183  // func isBaseType(t reflect.Type) bool {
   184  // 	for {
   185  // 		k := t.Kind()
   186  // 		switch k {
   187  // 		case reflect.String:
   188  // 			return true
   189  // 		case reflect.Bool:
   190  // 			return true
   191  // 		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   192  // 			return true
   193  // 		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   194  // 			return true
   195  // 		case reflect.Float32, reflect.Float64:
   196  // 			return true
   197  // 		case reflect.Ptr:
   198  // 			t = t.Elem()
   199  // 		default:
   200  // 			return false
   201  // 		}
   202  // 	}
   203  // }
   204  
   205  func (enc DefaultEncoders) EncodeDatastoreKey(_ reflext.StructFielder, v reflect.Value) (interface{}, error) {
   206  	key := v.Interface().(datastore.Key)
   207  	kk, pp := splitKey(&key)
   208  	return strings.Trim(pp+"/"+kk, "/"), nil
   209  }
   210  
   211  func splitKey(k *datastore.Key) (key string, parent string) {
   212  	if k == nil {
   213  		return "", ""
   214  	}
   215  	if k.ID > 0 {
   216  		return strconv.FormatInt(k.ID, 10), stringifyKey(k.Parent)
   217  	}
   218  	name := url.PathEscape(k.Name)
   219  	return "'" + name + "'", stringifyKey(k.Parent)
   220  }
   221  
   222  func stringifyKey(key *datastore.Key) string {
   223  	paths := make([]string, 0)
   224  	parentKey := key
   225  
   226  	for parentKey != nil {
   227  		var k string
   228  		if parentKey.Name != "" {
   229  			name := url.PathEscape(parentKey.Name)
   230  			k = parentKey.Kind + ",'" + name + "'"
   231  		} else {
   232  			k = parentKey.Kind + "," + strconv.FormatInt(parentKey.ID, 10)
   233  		}
   234  		paths = append([]string{k}, paths...)
   235  		parentKey = parentKey.Parent
   236  	}
   237  
   238  	if len(paths) > 0 {
   239  		return strings.Join(paths, "/")
   240  	}
   241  
   242  	return ""
   243  }