mirror of
https://github.com/danog/liquid.git
synced 2024-11-27 03:14:39 +01:00
Convert returns an error; create MustConvert
This commit is contained in:
parent
e2fd3bbf81
commit
4df3f04aae
@ -33,7 +33,7 @@ func convertArguments(fn reflect.Value, in []interface{}) []reflect.Value {
|
||||
if arg == nil {
|
||||
out[i] = reflect.Zero(rt.In(i))
|
||||
} else {
|
||||
out[i] = Convert(arg, rt.In(i))
|
||||
out[i] = reflect.ValueOf(MustConvert(arg, rt.In(i)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,51 +8,49 @@ import (
|
||||
|
||||
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
|
||||
// recursively create new map and slice values as necessary. It doesn't
|
||||
// handle circular references.
|
||||
//
|
||||
// TODO It's weird that this takes an interface{} but returns a Value
|
||||
func Convert(value interface{}, t reflect.Type) reflect.Value {
|
||||
func Convert(value interface{}, t reflect.Type) (interface{}, error) {
|
||||
r := reflect.ValueOf(value)
|
||||
if r.Type().ConvertibleTo(t) {
|
||||
return r.Convert(t)
|
||||
return r.Convert(t).Interface(), nil
|
||||
}
|
||||
if reflect.PtrTo(r.Type()) == t {
|
||||
return reflect.ValueOf(&value)
|
||||
return &value, nil
|
||||
}
|
||||
if r.Kind() == reflect.String && t == timeType {
|
||||
v, err := ParseTime(value.(string))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return reflect.ValueOf(v)
|
||||
return ParseTime(value.(string))
|
||||
}
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n, err := strconv.Atoi(value.(string))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return reflect.ValueOf(n)
|
||||
return strconv.Atoi(value.(string))
|
||||
case reflect.Float32, reflect.Float64:
|
||||
n, err := strconv.ParseFloat(value.(string), 64)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return reflect.ValueOf(n)
|
||||
return strconv.ParseFloat(value.(string), 64)
|
||||
case reflect.Slice:
|
||||
if r.Kind() != reflect.Array && r.Kind() != reflect.Slice {
|
||||
break
|
||||
}
|
||||
x := reflect.MakeSlice(t, 0, r.Len())
|
||||
out := reflect.MakeSlice(t, 0, r.Len())
|
||||
for i := 0; i < r.Len(); i++ {
|
||||
c := Convert(r.Index(i).Interface(), t.Elem())
|
||||
x = reflect.Append(x, c)
|
||||
item, err := Convert(r.Index(i).Interface(), t.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = reflect.Append(out, reflect.ValueOf(item))
|
||||
}
|
||||
return x
|
||||
return out.Interface(), nil
|
||||
}
|
||||
panic(genericErrorf("generic.Convert can't convert %#v<%s> to %v", value, r.Type(), t))
|
||||
return nil, genericErrorf("generic.Convert can't convert %#v<%s> to %v", value, r.Type(), t)
|
||||
}
|
||||
|
||||
var dateLayouts = []string{
|
||||
|
@ -65,7 +65,8 @@ func TestConvert(t *testing.T) {
|
||||
for i, test := range convertTests {
|
||||
t.Run(fmt.Sprintf("%02d", i+1), func(t *testing.T) {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user