1package pflag 2 3import ( 4 "fmt" 5 "io" 6 "net" 7 "strings" 8) 9 10// -- ipSlice Value 11type ipSliceValue struct { 12 value *[]net.IP 13 changed bool 14} 15 16func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue { 17 ipsv := new(ipSliceValue) 18 ipsv.value = p 19 *ipsv.value = val 20 return ipsv 21} 22 23// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag. 24// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended. 25func (s *ipSliceValue) Set(val string) error { 26 27 // remove all quote characters 28 rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") 29 30 // read flag arguments with CSV parser 31 ipStrSlice, err := readAsCSV(rmQuote.Replace(val)) 32 if err != nil && err != io.EOF { 33 return err 34 } 35 36 // parse ip values into slice 37 out := make([]net.IP, 0, len(ipStrSlice)) 38 for _, ipStr := range ipStrSlice { 39 ip := net.ParseIP(strings.TrimSpace(ipStr)) 40 if ip == nil { 41 return fmt.Errorf("invalid string being converted to IP address: %s", ipStr) 42 } 43 out = append(out, ip) 44 } 45 46 if !s.changed { 47 *s.value = out 48 } else { 49 *s.value = append(*s.value, out...) 50 } 51 52 s.changed = true 53 54 return nil 55} 56 57// Type returns a string that uniquely represents this flag's type. 58func (s *ipSliceValue) Type() string { 59 return "ipSlice" 60} 61 62// String defines a "native" format for this net.IP slice flag value. 63func (s *ipSliceValue) String() string { 64 65 ipStrSlice := make([]string, len(*s.value)) 66 for i, ip := range *s.value { 67 ipStrSlice[i] = ip.String() 68 } 69 70 out, _ := writeAsCSV(ipStrSlice) 71 72 return "[" + out + "]" 73} 74 75func ipSliceConv(val string) (interface{}, error) { 76 val = strings.Trim(val, "[]") 77 // Emtpy string would cause a slice with one (empty) entry 78 if len(val) == 0 { 79 return []net.IP{}, nil 80 } 81 ss := strings.Split(val, ",") 82 out := make([]net.IP, len(ss)) 83 for i, sval := range ss { 84 ip := net.ParseIP(strings.TrimSpace(sval)) 85 if ip == nil { 86 return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) 87 } 88 out[i] = ip 89 } 90 return out, nil 91} 92 93// GetIPSlice returns the []net.IP value of a flag with the given name 94func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) { 95 val, err := f.getFlagType(name, "ipSlice", ipSliceConv) 96 if err != nil { 97 return []net.IP{}, err 98 } 99 return val.([]net.IP), nil 100} 101 102// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string. 103// The argument p points to a []net.IP variable in which to store the value of the flag. 104func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { 105 f.VarP(newIPSliceValue(value, p), name, "", usage) 106} 107 108// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. 109func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { 110 f.VarP(newIPSliceValue(value, p), name, shorthand, usage) 111} 112 113// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string. 114// The argument p points to a []net.IP variable in which to store the value of the flag. 115func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { 116 CommandLine.VarP(newIPSliceValue(value, p), name, "", usage) 117} 118 119// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. 120func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { 121 CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage) 122} 123 124// IPSlice defines a []net.IP flag with specified name, default value, and usage string. 125// The return value is the address of a []net.IP variable that stores the value of that flag. 126func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP { 127 p := []net.IP{} 128 f.IPSliceVarP(&p, name, "", value, usage) 129 return &p 130} 131 132// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. 133func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { 134 p := []net.IP{} 135 f.IPSliceVarP(&p, name, shorthand, value, usage) 136 return &p 137} 138 139// IPSlice defines a []net.IP flag with specified name, default value, and usage string. 140// The return value is the address of a []net.IP variable that stores the value of the flag. 141func IPSlice(name string, value []net.IP, usage string) *[]net.IP { 142 return CommandLine.IPSliceP(name, "", value, usage) 143} 144 145// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. 146func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { 147 return CommandLine.IPSliceP(name, shorthand, value, usage) 148} 149