1
0
mirror of https://github.com/danog/liquid.git synced 2024-11-27 08:44:40 +01:00

Convert returns an error; create MustConvert

This commit is contained in:
Oliver Steele 2017-06-29 08:42:24 -04:00
parent e2fd3bbf81
commit 4df3f04aae
3 changed files with 26 additions and 27 deletions

View File

@ -33,7 +33,7 @@ func convertArguments(fn reflect.Value, in []interface{}) []reflect.Value {
if arg == nil { if arg == nil {
out[i] = reflect.Zero(rt.In(i)) out[i] = reflect.Zero(rt.In(i))
} else { } else {
out[i] = Convert(arg, rt.In(i)) out[i] = reflect.ValueOf(MustConvert(arg, rt.In(i)))
} }
} }
} }

View File

@ -8,51 +8,49 @@ import (
var timeType = reflect.TypeOf(time.Now()) var timeType = reflect.TypeOf(time.Now())
// MustConvert converts a value to the type.
func MustConvert(value interface{}, t reflect.Type) interface{} {
out, err := Convert(value, t)
if err != nil {
panic(err)
}
return out
}
// Convert value to the type. This is a more aggressive conversion, that will // Convert value to the type. This is a more aggressive conversion, that will
// recursively create new map and slice values as necessary. It doesn't // recursively create new map and slice values as necessary. It doesn't
// handle circular references. // handle circular references.
// func Convert(value interface{}, t reflect.Type) (interface{}, error) {
// TODO It's weird that this takes an interface{} but returns a Value
func Convert(value interface{}, t reflect.Type) reflect.Value {
r := reflect.ValueOf(value) r := reflect.ValueOf(value)
if r.Type().ConvertibleTo(t) { if r.Type().ConvertibleTo(t) {
return r.Convert(t) return r.Convert(t).Interface(), nil
} }
if reflect.PtrTo(r.Type()) == t { if reflect.PtrTo(r.Type()) == t {
return reflect.ValueOf(&value) return &value, nil
} }
if r.Kind() == reflect.String && t == timeType { if r.Kind() == reflect.String && t == timeType {
v, err := ParseTime(value.(string)) return ParseTime(value.(string))
if err != nil {
panic(err)
}
return reflect.ValueOf(v)
} }
switch t.Kind() { switch t.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.Atoi(value.(string)) return strconv.Atoi(value.(string))
if err != nil {
panic(err)
}
return reflect.ValueOf(n)
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(value.(string), 64) return strconv.ParseFloat(value.(string), 64)
if err != nil {
panic(err)
}
return reflect.ValueOf(n)
case reflect.Slice: case reflect.Slice:
if r.Kind() != reflect.Array && r.Kind() != reflect.Slice { if r.Kind() != reflect.Array && r.Kind() != reflect.Slice {
break break
} }
x := reflect.MakeSlice(t, 0, r.Len()) out := reflect.MakeSlice(t, 0, r.Len())
for i := 0; i < r.Len(); i++ { for i := 0; i < r.Len(); i++ {
c := Convert(r.Index(i).Interface(), t.Elem()) item, err := Convert(r.Index(i).Interface(), t.Elem())
x = reflect.Append(x, c) if err != nil {
return nil, err
} }
return x out = reflect.Append(out, reflect.ValueOf(item))
} }
panic(genericErrorf("generic.Convert can't convert %#v<%s> to %v", value, r.Type(), t)) return out.Interface(), nil
}
return nil, genericErrorf("generic.Convert can't convert %#v<%s> to %v", value, r.Type(), t)
} }
var dateLayouts = []string{ var dateLayouts = []string{

View File

@ -65,7 +65,8 @@ func TestConvert(t *testing.T) {
for i, test := range convertTests { for i, test := range convertTests {
t.Run(fmt.Sprintf("%02d", i+1), func(t *testing.T) { t.Run(fmt.Sprintf("%02d", i+1), func(t *testing.T) {
typ := reflect.TypeOf(test.proto) typ := reflect.TypeOf(test.proto)
value := Convert(test.value, typ).Interface() value, err := Convert(test.value, typ)
require.NoError(t, err)
require.Equalf(t, test.expected, value, "Convert %#v -> %#v", test.value, test, typ) require.Equalf(t, test.expected, value, "Convert %#v -> %#v", test.value, test, typ)
}) })
} }