439 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			439 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package decoder
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"strconv"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	nilValue = reflect.ValueOf(nil)
 | |
| )
 | |
| 
 | |
| func AssignValue(src, dst reflect.Value) error {
 | |
| 	if dst.Type().Kind() != reflect.Ptr {
 | |
| 		return fmt.Errorf("invalid dst type. required pointer type: %T", dst.Type())
 | |
| 	}
 | |
| 	casted, err := castValue(dst.Elem().Type(), src)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	dst.Elem().Set(casted)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func castValue(t reflect.Type, v reflect.Value) (reflect.Value, error) {
 | |
| 	switch t.Kind() {
 | |
| 	case reflect.Int:
 | |
| 		vv, err := castInt(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(int(vv.Int())), nil
 | |
| 	case reflect.Int8:
 | |
| 		vv, err := castInt(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(int8(vv.Int())), nil
 | |
| 	case reflect.Int16:
 | |
| 		vv, err := castInt(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(int16(vv.Int())), nil
 | |
| 	case reflect.Int32:
 | |
| 		vv, err := castInt(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(int32(vv.Int())), nil
 | |
| 	case reflect.Int64:
 | |
| 		return castInt(v)
 | |
| 	case reflect.Uint:
 | |
| 		vv, err := castUint(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(uint(vv.Uint())), nil
 | |
| 	case reflect.Uint8:
 | |
| 		vv, err := castUint(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(uint8(vv.Uint())), nil
 | |
| 	case reflect.Uint16:
 | |
| 		vv, err := castUint(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(uint16(vv.Uint())), nil
 | |
| 	case reflect.Uint32:
 | |
| 		vv, err := castUint(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(uint32(vv.Uint())), nil
 | |
| 	case reflect.Uint64:
 | |
| 		return castUint(v)
 | |
| 	case reflect.Uintptr:
 | |
| 		vv, err := castUint(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(uintptr(vv.Uint())), nil
 | |
| 	case reflect.String:
 | |
| 		return castString(v)
 | |
| 	case reflect.Bool:
 | |
| 		return castBool(v)
 | |
| 	case reflect.Float32:
 | |
| 		vv, err := castFloat(v)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(float32(vv.Float())), nil
 | |
| 	case reflect.Float64:
 | |
| 		return castFloat(v)
 | |
| 	case reflect.Array:
 | |
| 		return castArray(t, v)
 | |
| 	case reflect.Slice:
 | |
| 		return castSlice(t, v)
 | |
| 	case reflect.Map:
 | |
| 		return castMap(t, v)
 | |
| 	case reflect.Struct:
 | |
| 		return castStruct(t, v)
 | |
| 	}
 | |
| 	return v, nil
 | |
| }
 | |
| 
 | |
| func castInt(v reflect.Value) (reflect.Value, error) {
 | |
| 	switch v.Type().Kind() {
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		return v, nil
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		return reflect.ValueOf(int64(v.Uint())), nil
 | |
| 	case reflect.String:
 | |
| 		i64, err := strconv.ParseInt(v.String(), 10, 64)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(i64), nil
 | |
| 	case reflect.Bool:
 | |
| 		if v.Bool() {
 | |
| 			return reflect.ValueOf(int64(1)), nil
 | |
| 		}
 | |
| 		return reflect.ValueOf(int64(0)), nil
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return reflect.ValueOf(int64(v.Float())), nil
 | |
| 	case reflect.Array:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castInt(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to int64 from empty array")
 | |
| 	case reflect.Slice:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castInt(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to int64 from empty slice")
 | |
| 	case reflect.Interface:
 | |
| 		return castInt(reflect.ValueOf(v.Interface()))
 | |
| 	case reflect.Map:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to int64 from map")
 | |
| 	case reflect.Struct:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to int64 from struct")
 | |
| 	case reflect.Ptr:
 | |
| 		return castInt(v.Elem())
 | |
| 	}
 | |
| 	return nilValue, fmt.Errorf("failed to cast to int64 from %s", v.Type().Kind())
 | |
| }
 | |
| 
 | |
| func castUint(v reflect.Value) (reflect.Value, error) {
 | |
| 	switch v.Type().Kind() {
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		return reflect.ValueOf(uint64(v.Int())), nil
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		return v, nil
 | |
| 	case reflect.String:
 | |
| 		u64, err := strconv.ParseUint(v.String(), 10, 64)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(u64), nil
 | |
| 	case reflect.Bool:
 | |
| 		if v.Bool() {
 | |
| 			return reflect.ValueOf(uint64(1)), nil
 | |
| 		}
 | |
| 		return reflect.ValueOf(uint64(0)), nil
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return reflect.ValueOf(uint64(v.Float())), nil
 | |
| 	case reflect.Array:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castUint(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to uint64 from empty array")
 | |
| 	case reflect.Slice:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castUint(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to uint64 from empty slice")
 | |
| 	case reflect.Interface:
 | |
| 		return castUint(reflect.ValueOf(v.Interface()))
 | |
| 	case reflect.Map:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to uint64 from map")
 | |
| 	case reflect.Struct:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to uint64 from struct")
 | |
| 	case reflect.Ptr:
 | |
| 		return castUint(v.Elem())
 | |
| 	}
 | |
| 	return nilValue, fmt.Errorf("failed to cast to uint64 from %s", v.Type().Kind())
 | |
| }
 | |
| 
 | |
| func castString(v reflect.Value) (reflect.Value, error) {
 | |
| 	switch v.Type().Kind() {
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		return reflect.ValueOf(fmt.Sprint(v.Int())), nil
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		return reflect.ValueOf(fmt.Sprint(v.Uint())), nil
 | |
| 	case reflect.String:
 | |
| 		return v, nil
 | |
| 	case reflect.Bool:
 | |
| 		if v.Bool() {
 | |
| 			return reflect.ValueOf("true"), nil
 | |
| 		}
 | |
| 		return reflect.ValueOf("false"), nil
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return reflect.ValueOf(fmt.Sprint(v.Float())), nil
 | |
| 	case reflect.Array:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castString(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from empty array")
 | |
| 	case reflect.Slice:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castString(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from empty slice")
 | |
| 	case reflect.Interface:
 | |
| 		return castString(reflect.ValueOf(v.Interface()))
 | |
| 	case reflect.Map:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from map")
 | |
| 	case reflect.Struct:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from struct")
 | |
| 	case reflect.Ptr:
 | |
| 		return castString(v.Elem())
 | |
| 	}
 | |
| 	return nilValue, fmt.Errorf("failed to cast to string from %s", v.Type().Kind())
 | |
| }
 | |
| 
 | |
| func castBool(v reflect.Value) (reflect.Value, error) {
 | |
| 	switch v.Type().Kind() {
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		switch v.Int() {
 | |
| 		case 0:
 | |
| 			return reflect.ValueOf(false), nil
 | |
| 		case 1:
 | |
| 			return reflect.ValueOf(true), nil
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Int())
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		switch v.Uint() {
 | |
| 		case 0:
 | |
| 			return reflect.ValueOf(false), nil
 | |
| 		case 1:
 | |
| 			return reflect.ValueOf(true), nil
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Uint())
 | |
| 	case reflect.String:
 | |
| 		b, err := strconv.ParseBool(v.String())
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(b), nil
 | |
| 	case reflect.Bool:
 | |
| 		return v, nil
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		switch v.Float() {
 | |
| 		case 0:
 | |
| 			return reflect.ValueOf(false), nil
 | |
| 		case 1:
 | |
| 			return reflect.ValueOf(true), nil
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to bool from %f", v.Float())
 | |
| 	case reflect.Array:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castBool(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from empty array")
 | |
| 	case reflect.Slice:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castBool(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from empty slice")
 | |
| 	case reflect.Interface:
 | |
| 		return castBool(reflect.ValueOf(v.Interface()))
 | |
| 	case reflect.Map:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from map")
 | |
| 	case reflect.Struct:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to string from struct")
 | |
| 	case reflect.Ptr:
 | |
| 		return castBool(v.Elem())
 | |
| 	}
 | |
| 	return nilValue, fmt.Errorf("failed to cast to bool from %s", v.Type().Kind())
 | |
| }
 | |
| 
 | |
| func castFloat(v reflect.Value) (reflect.Value, error) {
 | |
| 	switch v.Type().Kind() {
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		return reflect.ValueOf(float64(v.Int())), nil
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		return reflect.ValueOf(float64(v.Uint())), nil
 | |
| 	case reflect.String:
 | |
| 		f64, err := strconv.ParseFloat(v.String(), 64)
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		return reflect.ValueOf(f64), nil
 | |
| 	case reflect.Bool:
 | |
| 		if v.Bool() {
 | |
| 			return reflect.ValueOf(float64(1)), nil
 | |
| 		}
 | |
| 		return reflect.ValueOf(float64(0)), nil
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return v, nil
 | |
| 	case reflect.Array:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castFloat(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to float64 from empty array")
 | |
| 	case reflect.Slice:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castFloat(v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to float64 from empty slice")
 | |
| 	case reflect.Interface:
 | |
| 		return castFloat(reflect.ValueOf(v.Interface()))
 | |
| 	case reflect.Map:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to float64 from map")
 | |
| 	case reflect.Struct:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to float64 from struct")
 | |
| 	case reflect.Ptr:
 | |
| 		return castFloat(v.Elem())
 | |
| 	}
 | |
| 	return nilValue, fmt.Errorf("failed to cast to float64 from %s", v.Type().Kind())
 | |
| }
 | |
| 
 | |
| func castArray(t reflect.Type, v reflect.Value) (reflect.Value, error) {
 | |
| 	kind := v.Type().Kind()
 | |
| 	if kind == reflect.Interface {
 | |
| 		return castArray(t, reflect.ValueOf(v.Interface()))
 | |
| 	}
 | |
| 	if kind != reflect.Slice && kind != reflect.Array {
 | |
| 		return nilValue, fmt.Errorf("failed to cast to array from %s", kind)
 | |
| 	}
 | |
| 	if t.Elem() == v.Type().Elem() {
 | |
| 		return v, nil
 | |
| 	}
 | |
| 	if t.Len() != v.Len() {
 | |
| 		return nilValue, fmt.Errorf("failed to cast [%d]array from slice of %d length", t.Len(), v.Len())
 | |
| 	}
 | |
| 	ret := reflect.New(t).Elem()
 | |
| 	for i := 0; i < v.Len(); i++ {
 | |
| 		vv, err := castValue(t.Elem(), v.Index(i))
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		ret.Index(i).Set(vv)
 | |
| 	}
 | |
| 	return ret, nil
 | |
| }
 | |
| 
 | |
| func castSlice(t reflect.Type, v reflect.Value) (reflect.Value, error) {
 | |
| 	kind := v.Type().Kind()
 | |
| 	if kind == reflect.Interface {
 | |
| 		return castSlice(t, reflect.ValueOf(v.Interface()))
 | |
| 	}
 | |
| 	if kind != reflect.Slice && kind != reflect.Array {
 | |
| 		return nilValue, fmt.Errorf("failed to cast to slice from %s", kind)
 | |
| 	}
 | |
| 	if t.Elem() == v.Type().Elem() {
 | |
| 		return v, nil
 | |
| 	}
 | |
| 	ret := reflect.MakeSlice(t, v.Len(), v.Len())
 | |
| 	for i := 0; i < v.Len(); i++ {
 | |
| 		vv, err := castValue(t.Elem(), v.Index(i))
 | |
| 		if err != nil {
 | |
| 			return nilValue, err
 | |
| 		}
 | |
| 		ret.Index(i).Set(vv)
 | |
| 	}
 | |
| 	return ret, nil
 | |
| }
 | |
| 
 | |
| func castMap(t reflect.Type, v reflect.Value) (reflect.Value, error) {
 | |
| 	ret := reflect.MakeMap(t)
 | |
| 	switch v.Type().Kind() {
 | |
| 	case reflect.Map:
 | |
| 		iter := v.MapRange()
 | |
| 		for iter.Next() {
 | |
| 			key, err := castValue(t.Key(), iter.Key())
 | |
| 			if err != nil {
 | |
| 				return nilValue, err
 | |
| 			}
 | |
| 			value, err := castValue(t.Elem(), iter.Value())
 | |
| 			if err != nil {
 | |
| 				return nilValue, err
 | |
| 			}
 | |
| 			ret.SetMapIndex(key, value)
 | |
| 		}
 | |
| 		return ret, nil
 | |
| 	case reflect.Interface:
 | |
| 		return castMap(t, reflect.ValueOf(v.Interface()))
 | |
| 	case reflect.Slice:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castMap(t, v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to map from empty slice")
 | |
| 	}
 | |
| 	return nilValue, fmt.Errorf("failed to cast to map from %s", v.Type().Kind())
 | |
| }
 | |
| 
 | |
| func castStruct(t reflect.Type, v reflect.Value) (reflect.Value, error) {
 | |
| 	ret := reflect.New(t).Elem()
 | |
| 	switch v.Type().Kind() {
 | |
| 	case reflect.Map:
 | |
| 		iter := v.MapRange()
 | |
| 		for iter.Next() {
 | |
| 			key := iter.Key()
 | |
| 			k, err := castString(key)
 | |
| 			if err != nil {
 | |
| 				return nilValue, err
 | |
| 			}
 | |
| 			fieldName := k.String()
 | |
| 			field, ok := t.FieldByName(fieldName)
 | |
| 			if ok {
 | |
| 				value, err := castValue(field.Type, iter.Value())
 | |
| 				if err != nil {
 | |
| 					return nilValue, err
 | |
| 				}
 | |
| 				ret.FieldByName(fieldName).Set(value)
 | |
| 			}
 | |
| 		}
 | |
| 		return ret, nil
 | |
| 	case reflect.Struct:
 | |
| 		for i := 0; i < v.Type().NumField(); i++ {
 | |
| 			name := v.Type().Field(i).Name
 | |
| 			ret.FieldByName(name).Set(v.FieldByName(name))
 | |
| 		}
 | |
| 		return ret, nil
 | |
| 	case reflect.Interface:
 | |
| 		return castStruct(t, reflect.ValueOf(v.Interface()))
 | |
| 	case reflect.Slice:
 | |
| 		if v.Len() > 0 {
 | |
| 			return castStruct(t, v.Index(0))
 | |
| 		}
 | |
| 		return nilValue, fmt.Errorf("failed to cast to struct from empty slice")
 | |
| 	default:
 | |
| 		return nilValue, fmt.Errorf("failed to cast to struct from %s", v.Type().Kind())
 | |
| 	}
 | |
| }
 |