1
0
mirror of https://github.com/danog/liquid.git synced 2024-12-02 18:47:54 +01:00
liquid/expressions/filters.go

68 lines
1.5 KiB
Go
Raw Normal View History

2017-06-27 00:55:12 +02:00
package expressions
import (
"fmt"
"reflect"
"github.com/osteele/liquid/errors"
2017-06-27 16:28:39 +02:00
"github.com/osteele/liquid/generics"
2017-06-27 00:55:12 +02:00
)
2017-06-27 15:17:57 +02:00
type InterpreterError string
func (e InterpreterError) Error() string { return string(e) }
2017-06-27 00:55:12 +02:00
type valueFn func(Context) interface{}
2017-06-27 03:32:08 +02:00
var filters = map[string]interface{}{}
func DefineFilter(name string, fn interface{}) {
rf := reflect.ValueOf(fn)
2017-06-27 15:17:57 +02:00
switch {
case rf.Kind() != reflect.Func:
panic(fmt.Errorf("a filter must be a function"))
case rf.Type().NumIn() < 1:
panic(fmt.Errorf("a filter function must have at least one input"))
case rf.Type().NumOut() > 2:
panic(fmt.Errorf("a filter must be have one or two outputs"))
// case rf.Type().Out(1).Implements(…):
// panic(fmt.Errorf("a filter's second output must be type error"))
2017-06-27 03:32:08 +02:00
}
filters[name] = fn
2017-06-27 00:55:12 +02:00
}
2017-06-27 03:32:08 +02:00
func makeFilter(f valueFn, name string, param valueFn) valueFn {
2017-06-27 00:55:12 +02:00
fn, ok := filters[name]
if !ok {
panic(errors.UndefinedFilter(name))
2017-06-27 00:55:12 +02:00
}
fr := reflect.ValueOf(fn)
return func(ctx Context) interface{} {
defer func() {
if r := recover(); r != nil {
switch e := r.(type) {
2017-06-27 16:28:39 +02:00
case generics.GenericError:
panic(InterpreterError(e.Error()))
default:
2017-06-27 15:17:57 +02:00
// fmt.Println(string(debug.Stack()))
panic(e)
}
}
}()
2017-06-27 00:55:12 +02:00
args := []interface{}{f(ctx)}
2017-06-27 03:32:08 +02:00
if param != nil {
args = append(args, param(ctx))
}
2017-06-27 16:28:39 +02:00
out, err := generics.Apply(fr, args)
2017-06-27 16:15:31 +02:00
if err != nil {
2017-06-27 15:17:57 +02:00
panic(err)
}
2017-06-27 16:15:31 +02:00
switch out := out.(type) {
2017-06-27 15:17:57 +02:00
case []byte:
return string(out)
default:
return out
}
2017-06-27 00:55:12 +02:00
}
}