gopkg.in/rethinkdb/rethinkdb-go.v6@v6.2.2/encoding/encoder_types.go (about)

     1  package encoding
     2  
     3  import (
     4  	"encoding/base64"
     5  	"fmt"
     6  	"math"
     7  	"reflect"
     8  	"time"
     9  )
    10  
    11  // newTypeEncoder constructs an encoderFunc for a type.
    12  // The returned encoder only checks CanAddr when allowAddr is true.
    13  func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
    14  	if t.Implements(marshalerType) {
    15  		return marshalerEncoder
    16  	}
    17  	if t.Kind() != reflect.Ptr && allowAddr {
    18  		if reflect.PtrTo(t).Implements(marshalerType) {
    19  			return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
    20  		}
    21  	}
    22  
    23  	// Check for psuedo-types first
    24  	switch t {
    25  	case timeType:
    26  		return timePseudoTypeEncoder
    27  	}
    28  
    29  	switch t.Kind() {
    30  	case reflect.Bool:
    31  		return boolEncoder
    32  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    33  		return intEncoder
    34  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    35  		return uintEncoder
    36  	case reflect.Float32:
    37  		return float32Encoder
    38  	case reflect.Float64:
    39  		return floatEncoder
    40  	case reflect.String:
    41  		return stringEncoder
    42  	case reflect.Interface:
    43  		return interfaceEncoder
    44  	case reflect.Struct:
    45  		return newStructEncoder(t)
    46  	case reflect.Map:
    47  		return newMapEncoder(t)
    48  	case reflect.Slice:
    49  		return newSliceEncoder(t)
    50  	case reflect.Array:
    51  		return newArrayEncoder(t)
    52  	case reflect.Ptr:
    53  		return newPtrEncoder(t)
    54  	case reflect.Func:
    55  		// functions are a special case as they can be used internally for
    56  		// optional arguments. Just return the raw function, if somebody tries
    57  		// to pass a function to the database the JSON marshaller will catch this
    58  		// anyway.
    59  		return funcEncoder
    60  	default:
    61  		return unsupportedTypeEncoder
    62  	}
    63  }
    64  
    65  func invalidValueEncoder(v reflect.Value) (interface{}, error) {
    66  	return nil, nil
    67  }
    68  
    69  func doNothingEncoder(v reflect.Value) (interface{}, error) {
    70  	return v.Interface(), nil
    71  }
    72  
    73  func marshalerEncoder(v reflect.Value) (interface{}, error) {
    74  	if v.Kind() == reflect.Ptr && v.IsNil() {
    75  		return nil, nil
    76  	}
    77  	m := v.Interface().(Marshaler)
    78  	ev, err := m.MarshalRQL()
    79  	if err != nil {
    80  		return nil, &MarshalerError{v.Type(), err}
    81  	}
    82  
    83  	return ev, nil
    84  }
    85  
    86  func addrMarshalerEncoder(v reflect.Value) (interface{}, error) {
    87  	va := v.Addr()
    88  	if va.IsNil() {
    89  		return nil, nil
    90  	}
    91  	m := va.Interface().(Marshaler)
    92  	ev, err := m.MarshalRQL()
    93  	if err != nil {
    94  		return nil, &MarshalerError{v.Type(), err}
    95  	}
    96  
    97  	return ev, nil
    98  }
    99  
   100  func boolEncoder(v reflect.Value) (interface{}, error) {
   101  	if v.Bool() {
   102  		return true, nil
   103  	} else {
   104  		return false, nil
   105  	}
   106  }
   107  
   108  func intEncoder(v reflect.Value) (interface{}, error) {
   109  	return v.Int(), nil
   110  }
   111  
   112  func uintEncoder(v reflect.Value) (interface{}, error) {
   113  	return v.Uint(), nil
   114  }
   115  
   116  func floatEncoder(v reflect.Value) (interface{}, error) {
   117  	return v.Float(), nil
   118  }
   119  
   120  func float32Encoder(v reflect.Value) (interface{}, error) {
   121  	return float32(v.Float()), nil
   122  }
   123  
   124  func stringEncoder(v reflect.Value) (interface{}, error) {
   125  	return v.String(), nil
   126  }
   127  
   128  func interfaceEncoder(v reflect.Value) (interface{}, error) {
   129  	if v.IsNil() {
   130  		return nil, nil
   131  	}
   132  	return encode(v.Elem())
   133  }
   134  
   135  func funcEncoder(v reflect.Value) (interface{}, error) {
   136  	if v.IsNil() {
   137  		return nil, nil
   138  	}
   139  	return v.Interface(), nil
   140  }
   141  
   142  func asStringEncoder(v reflect.Value) (interface{}, error) {
   143  	return fmt.Sprintf("%v", v.Interface()), nil
   144  }
   145  
   146  func unsupportedTypeEncoder(v reflect.Value) (interface{}, error) {
   147  	return nil, &UnsupportedTypeError{v.Type()}
   148  }
   149  
   150  type structEncoder struct {
   151  	fields    []field
   152  	fieldEncs []encoderFunc
   153  }
   154  
   155  func (se *structEncoder) encode(v reflect.Value) (interface{}, error) {
   156  	m := make(map[string]interface{})
   157  	for i, f := range se.fields {
   158  		fv := fieldByIndex(v, f.index)
   159  		if !fv.IsValid() || f.omitEmpty && se.isEmptyValue(fv) {
   160  			continue
   161  		}
   162  
   163  		encField, err := se.fieldEncs[i](fv)
   164  		if err != nil {
   165  			return nil, err
   166  		}
   167  
   168  		// If this field is a referenced field then attempt to extract the value.
   169  		if f.reference {
   170  			// Override the encoded field with the referenced field
   171  			encField = getReferenceField(f, v, encField)
   172  		}
   173  
   174  		if f.compound {
   175  			compoundField, ok := m[f.name].([]interface{})
   176  			if !ok {
   177  				compoundField = make([]interface{}, f.compoundIndex+1)
   178  			} else if len(compoundField) < f.compoundIndex+1 {
   179  				tmp := make([]interface{}, f.compoundIndex+1)
   180  				copy(tmp, compoundField)
   181  				compoundField = tmp
   182  			}
   183  
   184  			compoundField[f.compoundIndex] = encField
   185  			encField = compoundField
   186  		}
   187  
   188  		m[f.name] = encField
   189  	}
   190  
   191  	return m, nil
   192  }
   193  
   194  func getReferenceField(f field, v reflect.Value, encField interface{}) interface{} {
   195  	refName := f.name
   196  	if f.refName != "" {
   197  		refName = f.refName
   198  	}
   199  
   200  	encFields, isArray := encField.([]interface{})
   201  	if isArray {
   202  		refVals := make([]interface{}, len(encFields))
   203  		for i, e := range encFields {
   204  			refVals[i] = extractValue(e, v, f.name, refName)
   205  		}
   206  		return refVals
   207  	}
   208  	refVal := extractValue(encField, v, f.name, refName)
   209  	return refVal
   210  }
   211  
   212  func extractValue(encField interface{}, v reflect.Value, name string, refName string) interface{} {
   213  	// referenced fields can only handle maps so return an error if the
   214  	// encoded field is of a different type
   215  	m, ok := encField.(map[string]interface{})
   216  	if !ok {
   217  		err := fmt.Errorf("Error refing field %s in %s, expected object but got %t", refName, name, encField)
   218  		panic(&MarshalerError{v.Type(), err})
   219  	}
   220  	refVal, ok := m[refName]
   221  	if !ok {
   222  		err := fmt.Errorf("Error refing field %s in %s, could not find referenced field", refName, name)
   223  		panic(&MarshalerError{v.Type(), err})
   224  	}
   225  	return refVal
   226  }
   227  
   228  func (se *structEncoder) isEmptyValue(v reflect.Value) bool {
   229  	if v.Type() == timeType {
   230  		return v.Interface().(time.Time) == time.Time{}
   231  	}
   232  
   233  	return isEmptyValue(v)
   234  }
   235  
   236  func newStructEncoder(t reflect.Type) encoderFunc {
   237  	fields := cachedTypeFields(t)
   238  	se := &structEncoder{
   239  		fields:    fields,
   240  		fieldEncs: make([]encoderFunc, len(fields)),
   241  	}
   242  	for i, f := range fields {
   243  		se.fieldEncs[i] = typeEncoder(typeByIndex(t, f.index))
   244  	}
   245  	return se.encode
   246  }
   247  
   248  type mapEncoder struct {
   249  	keyEnc, elemEnc encoderFunc
   250  }
   251  
   252  func (me *mapEncoder) encode(v reflect.Value) (interface{}, error) {
   253  	if v.IsNil() {
   254  		return nil, nil
   255  	}
   256  
   257  	m := make(map[string]interface{})
   258  
   259  	for _, k := range v.MapKeys() {
   260  		encV, err := me.elemEnc(v.MapIndex(k))
   261  		if err != nil {
   262  			return nil, err
   263  		}
   264  		encK, err := me.keyEnc(k)
   265  		if err != nil {
   266  			return nil, err
   267  		}
   268  		m[encK.(string)] = encV
   269  	}
   270  
   271  	return m, nil
   272  }
   273  
   274  func newMapEncoder(t reflect.Type) encoderFunc {
   275  	var keyEnc encoderFunc
   276  	switch t.Key().Kind() {
   277  	case reflect.Bool:
   278  		keyEnc = asStringEncoder
   279  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   280  		keyEnc = asStringEncoder
   281  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   282  		keyEnc = asStringEncoder
   283  	case reflect.Float32, reflect.Float64:
   284  		keyEnc = asStringEncoder
   285  	case reflect.String:
   286  		keyEnc = stringEncoder
   287  	case reflect.Interface:
   288  		keyEnc = asStringEncoder
   289  	default:
   290  		return unsupportedTypeEncoder
   291  	}
   292  
   293  	me := &mapEncoder{keyEnc, typeEncoder(t.Elem())}
   294  	return me.encode
   295  }
   296  
   297  // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
   298  type sliceEncoder struct {
   299  	arrayEnc encoderFunc
   300  }
   301  
   302  func (se *sliceEncoder) encode(v reflect.Value) (interface{}, error) {
   303  	if v.IsNil() {
   304  		return []interface{}(nil), nil
   305  	}
   306  	return se.arrayEnc(v)
   307  }
   308  
   309  func newSliceEncoder(t reflect.Type) encoderFunc {
   310  	// Byte slices get special treatment; arrays don't.
   311  	if t.Elem().Kind() == reflect.Uint8 {
   312  		return encodeByteSlice
   313  	}
   314  	enc := &sliceEncoder{newArrayEncoder(t)}
   315  	return enc.encode
   316  }
   317  
   318  type arrayEncoder struct {
   319  	elemEnc encoderFunc
   320  }
   321  
   322  func (ae *arrayEncoder) encode(v reflect.Value) (interface{}, error) {
   323  	n := v.Len()
   324  
   325  	a := make([]interface{}, n)
   326  	for i := 0; i < n; i++ {
   327  		var err error
   328  		a[i], err = ae.elemEnc(v.Index(i))
   329  		if err != nil {
   330  			return nil, err
   331  		}
   332  	}
   333  
   334  	return a, nil
   335  }
   336  
   337  func newArrayEncoder(t reflect.Type) encoderFunc {
   338  	if t.Elem().Kind() == reflect.Uint8 {
   339  		return encodeByteArray
   340  	}
   341  	enc := &arrayEncoder{typeEncoder(t.Elem())}
   342  	return enc.encode
   343  }
   344  
   345  type ptrEncoder struct {
   346  	elemEnc encoderFunc
   347  }
   348  
   349  func (pe *ptrEncoder) encode(v reflect.Value) (interface{}, error) {
   350  	if v.IsNil() {
   351  		return nil, nil
   352  	}
   353  	return pe.elemEnc(v.Elem())
   354  }
   355  
   356  func newPtrEncoder(t reflect.Type) encoderFunc {
   357  	enc := &ptrEncoder{typeEncoder(t.Elem())}
   358  	return enc.encode
   359  }
   360  
   361  type condAddrEncoder struct {
   362  	canAddrEnc, elseEnc encoderFunc
   363  }
   364  
   365  func (ce *condAddrEncoder) encode(v reflect.Value) (interface{}, error) {
   366  	if v.CanAddr() {
   367  		return ce.canAddrEnc(v)
   368  	} else {
   369  		return ce.elseEnc(v)
   370  	}
   371  }
   372  
   373  // newCondAddrEncoder returns an encoder that checks whether its value
   374  // CanAddr and delegates to canAddrEnc if so, else to elseEnc.
   375  func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
   376  	enc := &condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
   377  	return enc.encode
   378  }
   379  
   380  // Pseudo-type encoders
   381  
   382  // Encode a time.Time value to the TIME RQL type
   383  func timePseudoTypeEncoder(v reflect.Value) (interface{}, error) {
   384  	t := v.Interface().(time.Time)
   385  
   386  	timeVal := float64(t.UnixNano()) / float64(time.Second)
   387  
   388  	// use seconds-since-epoch precision if time.Time `t`
   389  	// is before the oldest nanosecond time
   390  	if t.Before(time.Unix(0, math.MinInt64)) {
   391  		timeVal = float64(t.Unix())
   392  	}
   393  
   394  	return map[string]interface{}{
   395  		"$reql_type$": "TIME",
   396  		"epoch_time":  timeVal,
   397  		"timezone":    t.Format("-07:00"),
   398  	}, nil
   399  }
   400  
   401  // Encode a byte slice to the BINARY RQL type
   402  func encodeByteSlice(v reflect.Value) (interface{}, error) {
   403  	var b []byte
   404  	if !v.IsNil() {
   405  		b = v.Bytes()
   406  	}
   407  
   408  	dst := make([]byte, base64.StdEncoding.EncodedLen(len(b)))
   409  	base64.StdEncoding.Encode(dst, b)
   410  
   411  	return map[string]interface{}{
   412  		"$reql_type$": "BINARY",
   413  		"data":        string(dst),
   414  	}, nil
   415  }
   416  
   417  // Encode a byte array to the BINARY RQL type
   418  func encodeByteArray(v reflect.Value) (interface{}, error) {
   419  	b := make([]byte, v.Len())
   420  	for i := 0; i < v.Len(); i++ {
   421  		b[i] = v.Index(i).Interface().(byte)
   422  	}
   423  
   424  	dst := make([]byte, base64.StdEncoding.EncodedLen(len(b)))
   425  	base64.StdEncoding.Encode(dst, b)
   426  
   427  	return map[string]interface{}{
   428  		"$reql_type$": "BINARY",
   429  		"data":        string(dst),
   430  	}, nil
   431  }