diff options
| author | Alex Flint <[email protected]> | 2016-01-23 21:07:42 -0800 |
|---|---|---|
| committer | Alex Flint <[email protected]> | 2016-01-23 21:07:42 -0800 |
| commit | 77dd0df006f564a0768ee7ddc194f08e328f864e (patch) | |
| tree | d71dab9fd1abdac627ed1d17616e226897c50093 /scalar.go | |
| parent | c0809e537fc01b4a33ced1bf56212837108d7264 (diff) | |
| parent | a1c72f6aa9b1972a6d0e0c47052e805a0f1f3656 (diff) | |
Merge pull request #31 from alexflint/parse_ip_mac_and_email
Parse IP addresses, MAC addresses, and email addresses
Diffstat (limited to 'scalar.go')
| -rw-r--r-- | scalar.go | 71 |
1 files changed, 69 insertions, 2 deletions
@@ -3,11 +3,57 @@ package arg import ( "encoding" "fmt" + "net" + "net/mail" "reflect" "strconv" "time" ) +// The reflected form of some special types +var ( + textUnmarshalerType = reflect.TypeOf([]encoding.TextUnmarshaler{}).Elem() + durationType = reflect.TypeOf(time.Duration(0)) + mailAddressType = reflect.TypeOf(mail.Address{}) + ipType = reflect.TypeOf(net.IP{}) + macType = reflect.TypeOf(net.HardwareAddr{}) +) + +// isScalar returns true if the type can be parsed from a single string +func isScalar(t reflect.Type) (scalar, boolean bool) { + // If it implements encoding.TextUnmarshaler then use that + if t.Implements(textUnmarshalerType) { + // scalar=YES, boolean=NO + return true, false + } + + // If we have a pointer then dereference it + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + // Check for other special types + switch t { + case durationType, mailAddressType, ipType, macType: + // scalar=YES, boolean=NO + return true, false + } + + // Fall back to checking the kind + switch t.Kind() { + case reflect.Bool: + // scalar=YES, boolean=YES + return true, true + case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Float32, reflect.Float64: + // scalar=YES, boolean=NO + return true, false + } + // scalar=NO, boolean=NO + return false, false +} + // set a value from a string func setScalar(v reflect.Value, s string) error { if !v.CanSet() { @@ -35,11 +81,32 @@ func setScalar(v reflect.Value, s string) error { // Switch on concrete type switch scalar.(type) { case time.Duration: - x, err := time.ParseDuration(s) + duration, err := time.ParseDuration(s) + if err != nil { + return err + } + v.Set(reflect.ValueOf(duration)) + return nil + case mail.Address: + addr, err := mail.ParseAddress(s) + if err != nil { + return err + } + v.Set(reflect.ValueOf(*addr)) + return nil + case net.IP: + ip := net.ParseIP(s) + if ip == nil { + return fmt.Errorf(`invalid IP address: "%s"`, s) + } + v.Set(reflect.ValueOf(ip)) + return nil + case net.HardwareAddr: + ip, err := net.ParseMAC(s) if err != nil { return err } - v.Set(reflect.ValueOf(x)) + v.Set(reflect.ValueOf(ip)) return nil } |
