Binder
package revel
type Binder struct {
Bind func(params *Params, name string, typ reflect.Type) reflect.Value
Unbind func(output map[string]string, name string, val interface{})
}
func ValueBinder(f func(value string, typ reflect.Type) reflect.Value) func(*Params, string, reflect.Type) reflect.Value {
return func(params *Params, name string, typ reflect.Type) reflect.Value {
vals, ok := params.Values[name]
if !ok || len(vals) == 0 {
return reflect.Zero(typ)
}
return f(vals[0], typ)
}
}
const (
DEFAULT_DATE_FORMAT = "2006-01-02"
DEFAULT_DATETIME_FORMAT = "2006-01-02 15:04"
)
var (
TypeBinders = make(map[reflect.Type]Binder)
KindBinders = make(map[reflect.Kind]Binder)
TimeFormats = []string{}
DateFormat string
DateTimeFormat string
IntBinder = Binder{
Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value {
if len(val) == 0 {
return reflect.Zero(typ)
}
intValue, err := strconv.ParseInt(val, 10, 64)
if err != nil {
WARN.Println(err)
return reflect.Zero(typ)
}
pValue := reflect.New(typ)
pValue.Elem().SetInt(intValue)
return pValue.Elem()
}),
Unbind: func(output map[string]string, key string, val interface{}) {
output[key] = fmt.Sprintf("%d", val)
},
}
UintBinder = Binder{
Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value {
if len(val) == 0 {
return reflect.Zero(typ)
}
uintValue, err := strconv.ParseUint(val, 10, 64)
if err != nil {
WARN.Println(err)
return reflect.Zero(typ)
}
pValue := reflect.New(typ)
pValue.Elem().SetUint(uintValue)
return pValue.Elem()
}),
Unbind: func(output map[string]string, key string, val interface{}) {
output[key] = fmt.Sprintf("%d", val)
},
}
FloatBinder = Binder{
Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value {
if len(val) == 0 {
return reflect.Zero(typ)
}
floatValue, err := strconv.ParseFloat(val, 64)
if err != nil {
WARN.Println(err)
return reflect.Zero(typ)
}
pValue := reflect.New(typ)
pValue.Elem().SetFloat(floatValue)
return pValue.Elem()
}),
Unbind: func(output map[string]string, key string, val interface{}) {
output[key] = fmt.Sprintf("%f", val)
},
}
StringBinder = Binder{
Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value {
return reflect.ValueOf(val)
}),
Unbind: func(output map[string]string, name string, val interface{}) {
output[name] = val.(string)
},
}
BoolBinder = Binder{
Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value {
v := strings.TrimSpace(strings.ToLower(val))
switch v {
case "true", "on", "1":
return reflect.ValueOf(true)
}
return reflect.ValueOf(false)
}),
Unbind: func(output map[string]string, name string, val interface{}) {
output[name] = fmt.Sprintf("%t", val)
},
}
PointerBinder = Binder{
Bind: func(params *Params, name string, typ reflect.Type) reflect.Value {
return Bind(params, name, typ.Elem()).Addr()
},
Unbind: func(output map[string]string, name string, val interface{}) {
Unbind(output, name, reflect.ValueOf(val).Elem().Interface())
},
}
TimeBinder = Binder{
Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value {
for _, f := range TimeFormats {
if r, err := time.Parse(f, val); err == nil {
return reflect.ValueOf(r)
}
}
return reflect.Zero(typ)
}),
Unbind: func(output map[string]string, name string, val interface{}) {
var (
t = val.(time.Time)
format = DateTimeFormat
h, m, s = t.Clock()
)
if h == 0 && m == 0 && s == 0 {
format = DateFormat
}
output[name] = t.Format(format)
},
}
MapBinder = Binder{
Bind: bindMap,
Unbind: unbindMap,
}
)
func Bind(params *Params, name string, typ reflect.Type) reflect.Value {
if binder, found := binderForType(typ); found {
return binder.Bind(params, name, typ)
}
return reflect.Zero(typ)
}
func BindValue(val string, typ reflect.Type) reflect.Value {
return Bind(&Params{Values: map[string][]string{"": {val}}}, "", typ)
}
func BindFile(fileHeader *multipart.FileHeader, typ reflect.Type) reflect.Value {
return Bind(&Params{Files: map[string][]*multipart.FileHeader{"": {fileHeader}}}, "", typ)
}
func Unbind(output map[string]string, name string, val interface{}) {
if binder, found := binderForType(reflect.TypeOf(val)); found {
if binder.Unbind != nil {
binder.Unbind(output, name, val)
} else {
ERROR.Printf("revel/binder: can not unbind %s=%s", name, val)
}
}
}