refactor value parsing / setting
diff --git a/set.go b/set.go
index 5d1df26..e175eb4 100644
--- a/set.go
+++ b/set.go
@@ -19,6 +19,55 @@
})
}
+type setter func(destp interface{}, val string) error
+
+var setterUnsupportedType = fmt.Errorf("unsupported type")
+
+var setters = []setter{
+ stringSetter, boolSetter, textUnmarshalerSetter, scanSetter,
+}
+
+func stringSetter(d interface{}, val string) error {
+ dsp, ok := d.(*string)
+ if !ok {
+ return setterUnsupportedType
+ }
+ *dsp = val
+ return nil
+}
+
+func textUnmarshalerSetter(d interface{}, val string) error {
+ dtu, ok := d.(textUnmarshaler)
+ if !ok {
+ return setterUnsupportedType
+ }
+ return dtu.UnmarshalText([]byte(val))
+}
+
+func boolSetter(d interface{}, val string) error {
+ dbp, ok := d.(*bool)
+ if !ok {
+ return setterUnsupportedType
+ }
+ return (*gbool)(dbp).UnmarshalText([]byte(val))
+}
+
+func scanSetter(d interface{}, val string) error {
+ t := reflect.ValueOf(d).Elem().Type()
+ verb := scanverb(t)
+ // attempt to read an extra rune to make sure the value is consumed
+ var r rune
+ n, err := fmt.Sscanf(val, "%"+string(verb)+"%c", d, &r)
+ switch {
+ case n < 1 || n == 1 && err != io.EOF:
+ return fmt.Errorf("failed to parse %q as %v: %v", val, t, err)
+ case n > 1:
+ return fmt.Errorf("failed to parse %q as %v: extra characters", val, t)
+ }
+ // n == 1 && err == io.EOF
+ return nil
+}
+
var primitiveVerbs = map[reflect.Kind]rune{
reflect.Int: 'd',
reflect.Int8: 'd',
@@ -95,31 +144,20 @@
vAddr = vName.Addr()
}
vAddrI := vAddr.Interface()
- if v, ok := vAddrI.(*bool); ok {
- vAddrI = (*gbool)(v)
- }
- switch v := vAddrI.(type) {
- case *string:
- *v = value
- case textUnmarshaler:
- err := v.UnmarshalText([]byte(value))
- if err != nil {
+ err, ok := error(nil), false
+ for _, s := range setters {
+ err = s(vAddrI, value)
+ if err == nil {
+ ok = true
+ break
+ }
+ if err != setterUnsupportedType {
return err
}
- default:
- // attempt to read an extra rune to make sure the value is consumed
- var r rune
- verb := scanverb(vAddr.Elem().Type())
- n, err := fmt.Sscanf(value, "%"+string(verb)+"%c", vAddrI, &r)
- switch {
- case n < 1 || n == 1 && err != io.EOF:
- return fmt.Errorf("failed to parse %q as %v: %v", value, vName.Type(),
- err)
- case n > 1:
- return fmt.Errorf("failed to parse %q as %v: extra characters", value,
- vName.Type())
- }
- // n == 1 && err == io.EOF
+ }
+ if !ok {
+ // in case all setters returned setterUnsupportedType
+ return err
}
if isMulti {
vName.Set(reflect.Append(vName, vAddr.Elem()))